Kalender
Datum | Thema | Material |
---|---|---|
2019-10-25 | IPC, Netzwerkkommunikation als Client, Sockets | caseconv.c |
2019-10-31 | Übung entfällt | |
2019-11-08 | Übung entfällt | |
2019-11-15 | Netzwerkkommunikation als Server, Signale | troll.tar.gz |
2019-11-22 | Besprechung snail | |
2019-11-29 | Signale und Nebenläufigkeit, Vorbesprechung rush | waiter.c |
2019-12-06 | Besprechung sister | |
2019-12-13 | Synchronisation bei Nebenläufigkeit, Vorbesprechung jbuffer | |
2019-12-20 | Weihnachtshacking ^^ | exploit.c |
Tipps zu den Aufgaben
sister
- listen Socket vor der Anfragenbehandlung schließen Falls in der Anfragenbehandlung irgendwelche Sicherheitslücken bestehen, will man nicht dass der Angreifer mit anderen Clients reden kann.
-
getaddrinfo(3) für
struct sockaddr
ist optional Kann man machen wenn man will, ist für unsere Zwecke aber Overkill. Stattdessen kann man auch einfach einstruct sockaddr_in6
verwenden. Dann aber dashtons
nicht vergessen. -
Blockierende Systemaufrufe gegebenenfalls neustarten
Wenn während einem blockierenden Systemaufruf wie
accept(2) ein Signal
ankommt wird der Aufruf unterbrochen und setzt die
errno
aufEINTR
. Dann muss der Systemaufruf neugestartet werden.
Checkliste für Abgaben
- Fehlerbehandlung nicht vergessen :) In den manpages steht, welche Fehler während den jeweiligen Funktionen auftreten können.
-
Sichtbarkeit einschränken
Soweit möglich Funktionen und Variablen als
static
deklarieren. -
Bei Funktionen ohne Argumente, die Argumentliste mit
void
kennzeichen Ansonsten könnte man die Funktion mit einer beliebigen Anzahl an Parametern aufrufen. - Auch Randfälle testen Das Programm ist nicht korrekt, wenn es nur für "richtige" Eingaben das Richtige tut.
- Auf einem CIP-Rechner kompilieren Unterschiedliche Compiler(-versionen) werfen gerne unterschiedliche Warnungen. Die CIP-Rechner sind das Referenzsystem.
Fehlerbehandlung
Diese Art der Fehlerbehandlung ist inkorrekt:1 errno = 0;
2 int* foo = malloc(10);
3 if (errno) {
4 perror("malloc");
5 exit(EXIT_FAILURE);
6 }
Das liegt daran, dass eine Funktion, die erfolgreich ausgeführt wurde,
die errno
beliebig verändern darf (siehe dazu
auch errno(3)). Bei den meisten Funktionen wird im
Fehlerfall ein besonderer Rückgabewert gegeben (z.B NULL im Falle von malloc
). Nur wenn so ein Fehler erkannt wird darf
der Wert in errno
verwendet werden. Es ist
dann auch unnötig, die errno
vorher auf 0 zu
setzen.
Es gibt auch Ausnahmen die gesondert behandelt werden müssen, wie z.B
strtol(3). Das ist dann auf den jeweiligen
manpages vermerkt.
Compilerflags
Zusätzlich zu den vorgegebenen Flags lohnt es sich zum Testen noch ein paar mehr Compileroptionen zu setzen-
-g
Generiert Debugsymbole für besseres Debugging in gdb/valgrind -
-Wextra
Aktiviert zusätzliche Warnungen (tendenziell nervig) -
-Wformat=2
Fehler/potentielle Probleme bei der Verwendung von printf/scanf anzeigen -
-Wshadow
Warnt vor überschriebenen Variablen in Subscopes -
-Wconversion
Warnt vor problematischen Casts
exec(3) und execve(2)
Beim Lesen von exec(3) sieht man einen Haufen Funktionen die man alle ein wenig unterschiedlich aufrufen muss. Das sind Bibliotheksfunktionen die intern alle den gleichen Systemaufruf execve(2) verwenden. Die Buchstaben am Ende der Funktionsnamen der exec(3)-Familie bedeuten dabei:- l Übergebe argv als Argumentliste
- v Übergebe argv als Array
- p Durchsuche den PATH nach dem übergebenen Programm. Dadurch muss man keine absoluten Pfade zu den Programmen angeben.
argv
muss, egal ob als Liste oder als Array, immer mit
NULL
abgeschlossen werden.
Sonstiges
Ich betreue die Rechnerübung am Montag um 12-14 Uhr (zusammen mit Kilian). Den Semesterplan findet ihr auf der Lehrstuhlseite. Bei Fragen zu den Aufgaben (bzw. deren Korrektur, siehe auch Korrekturrichtlinien) und zu anderen SP-Themen könnt ihr mir gerne eine Mail schreiben. Alternativ gibt es als Anlaufstellen- Das SP-Unterforum im FSI-Forum
- Der #sp IRC-Channel (siehe IRC-Guide der FSI)
- Die Allgemeine und die Orga-Maillingliste