Nein ;). Ich meinte, ob wir uns Gedanken darum machen sollen, ob man vllt. durch Umbauen des Algorithmus, den wir verwenden, Anweisungen im kritischen Abschnitt sparen können.
Initialisierungen;
Lock();
if(...) {
Unlock();
return;
}
Unlock();
Mit Zeigern auf SBUF lesend zugreifen;
Lock();
SBUF verändern;
Unlock();
return;
Wobei ich mir bei zweiter Variante Gedanken machen muss, ob ich verschiedene Locks brauche und ob es überhaupt so geht.
Und die Alternative ist es einfach die ganze Methode zu synchronisieren und wenn das keine Punktabzüge gibt wäre es die weniger fehleranfällige Variante ;).
Allgemein musst du bei dem [m]unlock[/m]/[m]lock[/m] extrem aufpassen, dass es da keine Race-Conditions gibt. Häufig kann sich dazwischen dann doch irgendein Zustand ändern, sodass es kaputt geht.
Ich denke nicht, dass man das bei der piper sinnvoll trennen kann, da reicht ein [m]lock[/m] am Anfang und ein [m]unlock[/m] am Ende der Funktion. Auch kostet jedes Lock Zeit, ggf. mehr als man spart, wenn man einfach von Anfang bis Ende gelockt hat.
Woran liegt es, dass valgrind Speicherlecks entdeckt? An der fehlenden remove()-Funktion des sbuf?
Ist eine Implementierung der Aufgabe ohne Speicherleck überhaupt möglich? Immerhin kommt auch die Referenzimplementierung nicht ungeschoren durch valgrind…
Richtig. Es gibt keine Funktion, die den [m]SBUF[/m] wieder zerstört. Deswegen kommt man um Speicherlecks nicht herum.
Die API sollte da in Zukunft verbessert werden.
Außerdem sind beim [m]exit(3)[/m] wohl noch die [m]FILE *[/m] zu den Pipes offen, diese nutzen auch [m]malloc(3)[/m]. Je nachdem wie man die Threads erstellt hat, benötigen diese auch noch Speicher. Diese Lecks könnte man (und sollte man) aber auch mit der aktuellen API vermeiden.
Die [m]sbufGetNumberOfSems()[/m] würde kaputt gehen, wenn man [m]NULL[/m] übergibt. In dem h-Datei steht aber nichts von return-Werten im Fehlerfall. Soll man das dann einfach nicht behandeln? Bis jetzt hab ich nur ne spezielle Fehlermeldung, aber es wird danach trotzdem die fehlschlagende Funktion ausgeführt.
Die Schnittstelle gibt leider keinen speziellen Wert für den Fehlerfall vor. Daher würde ich einfach 0 zurückgeben, wenn ein NULL-Zeiger übergeben wird.
Irgendwo hab ich das tatsächlich schonmal gehört… danke für den Hinweis! Gilt das nur für eigene Fehlerausgaben oder soll man auch bei einem malloc fail keine perror Ausgabe machen?
Dann habe ich noch eine Frage, in der manpage vom fwrite steht nichts darüber drin, ob im Fehlerfall die errno gesetzt wird. Jetzt habe ich ein bisschen gegoogelt und was gefunden, dass alle stdio funktionen die errno im Fehlerfall setzen müssen - zumindest nach dem posix standard. Bin jetzt verwirrt…
In Bibliotheksfunktionen darf es niemals eine Fehlerausgabe geben (es sei denn das Programm wird terminiert). Natürlich auch dann keine, wenn [m]malloc(3)[/m] fehlschlägt. [m]perror(3)[/m] kann der Aufrufer aufrufen, falls er den Fehlergrund herausfinden will.
Stell dir einfach vor „was würde malloc machen“? [m]malloc(3)[/m] erzeugt im Fehlerfall auch keine Ausgabe.
Ja, [m]fwrite(3)[/m] und co. setzen die [m]errno[/m]. Das liegt einfach daran, dass sie [m]write(2)[/m] verwenden - und das setzt die [m]errno[/m]. Ist nicht ganz so schön, dass das nicht in der [m]fwrite(3)[/m] steht.
Ich finde nen Crash da jetzt nicht schlimm. Wenn man die Funktion falsch verwendet (in der API steht nichts davon, was bei [m]NULL[/m] passiert), dann kann es auch abstürzen. Aber kann man auch anders implementieren.