FAQ
Welche Vorkenntnisse sollte ich mitbringen?
Grundlegende Fähigkeiten in C oder einer Sprache mit C-ähnlicher Syntax werden benötigt. Die Kenntnisse aus der Vorlesung Algorithmen und Datenstrukturen reichen aus, um das Praktikum zu bestehen. Bei Problemen helfen die Betreuer gerne weiter, dazu richten wir eine Mailingliste ein. Erfahrungen mit Linux sind hilfreich, aber nicht nötig.
Die Kenntnisse für fortgeschrittene Lösungen (POSIX-Signale, Multithreading), die über das Bestehen hinaus auch im Turnier gut spielen, vermitteln wir individuell im Rahmen unserer Möglichkeiten.
Ich arbeite auf meinem Rechner mit Windows. Wie kann ich am einfachsten Linux installieren?
Wir empfehlen die Installation einer Linux-Distribution, z.B. Ubuntu 20.04.2, in einer virtuellen Maschine. Dazu besorgst Du Dir als erstes eine Virtualisierungssoftware wie das kostenlose VirtualBox. Diese wird als normales Windows-Programm installiert und stellt einen virtuellen Rechner zur Verfügung. Wir empfehlen, Ubuntu als OSBox herunterzuladen. Folge der Installationsanleitung (Benutzername: osboxes.org, Passwort: osboxes.org), installiere auch die Guest Addition.
Unter den Ubunut Settings kann die Auflösung (und somit die Fenstergröße) verändert werden. Ein Terminal findest du unter Activities.
Die Entwicklungswerkzeuge für die Erstellung von lauffähigen Programmen aus Quellcode können mit dem Paket build-essential über die Paketverwaltung installiert werden:
sudo apt update
sudo apt install build-essential
Um uns die Quellcode-Datei deines Spielers oder gegebenenfalls Fehlermeldungen schicken zu können, bietet es sich an, direkt aus der Linux-VM auf deinen Uni-Mail-Account zuzugreifen - zum Beispiel per Web-Browser oder indem du ein E-Mail-Programm (z.B. Thunderbird) einrichtest.
Alternativ kannst du auch den direkten Datenaustausch zwischen deinem Windows und der Linux-VM erlauben. Wenn du die Guest Addition installiert hast, kannst du unter Geräte die gemeinsame Zwischenablage aktivieren. Die Installation dieser Gasterweiterungen erfordert, dass du zuvor bereits die Entwicklungswerkzeuge build-essential über die Paketverwaltung installiert hast.
Neben der Installation in einer virtuellen Maschine kann Linux natürlich auch auf einer eigenen Partition zusätzlich zu Windows installiert werden.
Wie kann ich meinen Spieler zu Testzwecken mit einer ganz bestimmten Spiel-Situation füttern?
Ihr könnt euren Spieler mit folgendem Kommando direkt aufrufen:
./my_player 3<&0 4>&1
Das verbindet den File-Descriptor 3, über den der Spieler das Spielfeld erwartet, mit der Standard-Eingabe – in UNIX immer Nummer 0 – und den File-Descriptor 4, über den der Zug ausgegeben wird, mit der Standard-Ausgabe – in UNIX die Nummer 1. So kann interaktiv per Eingabe im Terminal ein beliebiges Spielfeld übergeben werden und der Spieler antwortet mit seinem Zug.
Welche Werkzeuge kann ich zum Debuggen verwenden?
Der Standard-Debugger unter Linux ist der GNU Debugger gdb. Das ist ein Kommandozeilen-Debugger, der für Einsteiger nicht ganz einfach zu bedienen ist, deshalb folgt eine kurze Einführung:
Falls ihr die Reaktion eures Spielers auf eine bestimmte Spielsituation genauer untersuchen wollt, hilft es oft, mit gdb durch das Programm Zeile für Zeile durchzugehen. Startet dafür zunächst gdb und übergebt euren Spieler als Argument, damit gdb die Symbole kennt:
gdb -tui my_player
Das zusätzliche Argument -tui sorgt dafür, dass ihr sowohl die gdb Kommandozeile seht, als auch euren Quellcode. Als nächstes solltet ihr einen Breakpoint setzen, z.B. auf main:
(gdb) b main
Anschließend könnt ihr das Programm mit dem run-Befehl starten, wobei ihr IO-Redirection verwenden könnt, um die Spielsituation von einer Datei einzulesen:
(gdb) run 3<eingabe.txt 4>ausgabe.txt 1>/dev/null 2>/dev/null
Ihr müsst also vorher die Datei eingabe.txt mit der Spielsituation füllen, die ihr untersuchen wollt, und der Zug, den euer Spieler normalerweise an den MCP sendet, landet in ausgabe.txt. Die Weiterleitung von 1 (stdout) und 2 (stderr) ist auch ratsam, weil ihr die Ausgaben sonst in gdb seht, was gerne mal das UI kaputt macht, sofern -tui verwendet wird. Nun läuft das Programm bis zur main-Funktion und ihr könnt mit den Befehlen s für step, n für next Zeile für Zeile untersuchen was passiert. Wichtig ist auch der Befehl p für print, um Werte von Variablen und Ähnliches auszugeben. Weitere Informationen zu den gdb-Befehlen bekommt ihr mit help <befehl>.
Wie kann ich Abstürze untersuchen?
Mit dem folgenden Kommandozeilenbefehl wird angeschaltet, dass bei jedem Absturz ein Speicherabbild des Prozesses in eine Datei core geschrieben wird:
ulimit -c unlimited
Ein solches Speicherabbild kann man post mortem mit gdb analysieren:
gdb my-player core
Ein weiteres Debugging-Werkzeug für Fortgeschrittenere ist Valgrind. Damit lassen sich sehr gut Speicher- und Thread-Fehler finden.
Wie bekomme ich in C++ dynamische Arrays?
Wer ein mitwachsendes Array benötigt, um zum Beispiel eine Liste aller möglichen gültigen Züge aufzubauen, sollte einen Blick auf die C++ Standard Template Library (STL) werfen, speziell auf die Klasse vector.
C-Programmierer (also ohne das ++) bekommen diesen Komfort nicht, können sich aber mit einer verketteten Liste oder mit dem manuellen Vergrößern von Datenbereichen per realloc() behelfen.
Ich will Zufallszahlen benutzen. Was muss ich beachten?
Die C-Funktion random() erzeugt brauchbare Pseudozufallszahlen (allerdings nicht gut genug für kryptografische Anwendungen). Der Zufallszahlen-Generator muss dazu einmal zu Beginn des Programms mit srandom() initialisiert werden.
Möchte man jedesmal dieselbe Folge von Pseudozufallszahlen erzeugen, zum Beispiel um Fehler im Programm leichter nachvollziehen zu können, dann empfiehlt sich die Initialisierung mit einem konstanten Wert. Möchte man bei jedem Lauf des Programms andere Pseudozufallszahlen haben, kann man zum Beispiel mit dem Ergebnis von time() initialisieren.
Ubuntu 22.02 Endlose AddressSanitizer:DEADLYSIGNAL Schleife
Dieser Fehler tritt in der aktuellen Version von Ubuntu 22.02 gcc auf und lässt sich recht einfach durch den folgenden Befehl lösen: sudo sysctl vm.mmap_rnd_bits=28
Weitere Informationen hier.