goto is evil
-
Original erstellt von DrGreenthumb:
**```cpp
rc = 0;
while( (rc = slow_syscall()) < 0 && errno == EINTR && restart );
if( rc < 0 ) {
perror("slow_syscall");
exit(EXIT_FAILURE);
}/* Mist.. is ja fast dasselbe wie von DrZoidberg */
-
da exit das Programm beendet, sollte dies äquivalent sein:
do { if ((rc = slow_syscall()) >= 0) break; if (errno != EINTR) { perror("slow_syscall"); exit(EXIT_FAILURE); } } while (restart);
Oder so:
while ((rc = slow_syscall())<0 && errno==EINTR && restart); if (rc < 0 && errno != EINTR) { perror("slow_syscall"); exit(EXIT_FAILURE); }
Die erste Lösung gefällt mir persönlich besser.
Das ganze 'Kapitel' wird durch do-while schön gekapselt, die Vergleiche
kommen nicht doppelt vor.
Das 'early-out' mit dem break ist eine einfache Anweisung,
das Loopkriterium offensichtlicher.[ Dieser Beitrag wurde am 14.11.2002 um 16:12 Uhr von Bitsy editiert. ]
-
wie sieht der code aus, den ihr gerne verwenden würdet? würde einer von euch gerne ne lösung verwenden von den hier genannten? oder was nehmt ihr sonst?
-
Ich würds bei dem goto belassen.
-
wie sieht der code aus, den ihr gerne verwenden würdet? würde einer von euch gerne ne lösung verwenden von den hier genannten? oder was nehmt ihr sonst?
Einen kontrollierten Buffer-Overflow
mfg
v R
-
@volkard:
Von der Form her würde ich meine erste Lösung vertreten (wieso steht ja dabei).
Um ganz ehrlich zu sein, mag ich aber exit generell nicht in einer 'tiefen' Routine.
Ich würde deshalb die Routine mit einem Fehlercode returnen, bzw. eine Exception werfen (wenn ich das endlich mal lernen würde).
-
Original erstellt von Bitsy:
@volkard:
Ich würde deshalb die Routine mit einem Fehlercode returnen, bzw. eine Exception werfen (wenn ich das endlich mal lernen würde).ok, mach statt
perror("slow_syscall");
exit(EXIT_FAILURE);
einfach throw "slow_syscall", ich denke bashar hat da nix dagegen, oder?
-
Dr. Zoidberg: Gefällt mir ganz gut.
Devil81: Sieht mir eher nach Vergewaltigung einer for-Schleife aus. Ausserdem ist das nicht richtig: Wenn restart false ist, wird der Systemaufruf gar nicht erst gemacht, ist es true, wird immer wieder restartet, egal ob EINTR oder nicht. Dazu sind rc und errno bei der ersten Iteration undefiniert.
Hexagon: Deine Schleife bricht im Normalfall auch nie ab.
Cengiz: Wenn restart == true, wird deine Schleife nicht betreten.
Dr Greenthumb: Nicht ganz richtig, wenn restart == false ist, aber der Syscall mit EINTR beendet wird, behandelst du das als fatalen Fehler.
Bitsy: Die erste Version wär auch mein erster Gedanke gewesen (hast du einen PAP gezeichnet und direkt umgeformt?:)) Hat IMHO 2 mini-Nachteile: Zum einen sehen die Bedingungen seltsam aus ... das "< 0" wird von jedem sofort als Fehler-Überprüfung erkannt, bei ">= 0" muß man erst nachdenken, genauso bei dem "!= EINTR". Zum anderen ist die Bedingung der do..while-Schleife konstant, man könnte das jetzt auch als Vergewaltigung des Sprachmittels ansehen.
Die zweite Version ist die von Dr. Greenthumb mit Korrektur. Ist OK. Ich kann mich nicht ganz entscheiden zwischen der und der von Dr. Zoidberg ... wobei ich nicht ganz überzeugt bin dass goto tatsächlich unpassend ist. Abgesehen davon dass es evil istIch hätte gar nicht gedacht, dass es soviele falsche Vorschläge gibt. Ist der Original-Code zu unverständlich -- oder ist fanatische goto-Vermeidung doch nicht so das gelbe vom Ei?
-
Original erstellt von Bashar:
Ich hätte gar nicht gedacht, dass es soviele falsche Vorschläge gibt. Ist der Original-Code zu unverständlich -- oder ist fanatische goto-Vermeidung doch nicht so das gelbe vom Ei?Definitiv unverständlich. Aber die semantik von slow_syscall() ist so unverständlich. Ein zweifach bedeutungsüberladener returnwert!!!
nu kanns sein, daß in anbetracht einer api mit solchen returnwerten das goto sinnvoll ist. müssen wir wenigstens glauben, solange keine gut lesbare lösung reinflattert.
hier sollten alle non-goto-dogmaten aufgefordert sein, ihr dogma zu verteidigen. *grins*
-
Original erstellt von volkard:
Ein zweifach bedeutungsüberladener returnwert!!!Nicht wirklich. < 0 ist Fehler, alles andere bedeutet korrekte Abarbeitung.
Nun gibt es solche und solche Fehlerursachen ... EINTR ist nun gerade ein Fehler, bei dem man es sofort nochmal versuchen kann, es sei denn man mißt dem Signal irgendeine Bedeutung bei, die das verhindert. Bei anderen Fehlern müßte man u.U. etwas Arbeit vor dem neustarten investieren, und bei manchen kann man nur noch aufgeben (Systemweites Semaphor unter dem ***** weggelöscht? Mist.)
-
ich hab gute erfahrungen gemacht, die ganze win32-api zu kapseln
durch exceptionwerfende inline-funktionen. mal sehen, ob linux
das auch mag...//da in der cpplinux.h inline int cpp_slow_syscall() {//die dreifache returnwertüberladung auflösen in nur einen //returnwert und zwei exceptions int rc=slow_syscall(); if(rc<0) if(errno==EINTR) throw Eintr(); else throw Error(errno); return rc; } //da wo der das timeout wegignorieren mag do { try { cpp_slow_syscall(); return;//break ist lame, und wers braucht, hat diese //funktion zu fett angelegt, füchte ich } catch(Eintr&) { } }while(again); //und irgenwo außen meinetwegen catch(Error& e) { perror("slow_syscall"); exit(EXIT_FAILURE); }
ich denke, mit meinem derzeitigen erkenntnisstand würde ich linux so benutzen. ich halts eigentlich für gut lesbar. was meinst du?
-
Also ich würde es so schreiben:
while(slow_syscall() < 0) { if(errno != EINTR) { perror("slow_syscall"); exit(EXIT_FAILURE); } if(!restart) break; }
-
Original erstellt von volkard:
wie sieht der code aus, den ihr gerne verwenden würdet?Der wurde wahrscheinlich nicht gepostet ...
Wenn es um leserlichen Code geht, würde ich die goto-Lösung lassen. Die ist ja auch mehr oder weniger üblich.
Wenn die Lösung absolut 'perfekt' werden soll (jede Bedingung wird 1x getestet + Grundsätzte der strukturierten Programmierung werden eingehalten) wird AFAICS ein do-While zum Einsatz kommen. Also Bitsys Code mit Würgaround für das break.
Ich persönlich habe aber mit dem do-While-Zeugs ein kleines Problem: ich muss immer nachdenken um mit dem Code klarzukommen ;).Bashar: Eigentlich hier OT, aber will man errno nicht vor slow_syscall () noch löschen? Ich mache das immer, wenn ich errno anschließend angucke.
-
errno wird doch garantiert verändert, wenn es einen Fehler gab. Andernfalls guck ich errno auch nicht an.
-
Original erstellt von Nemesyzz:
Also ich würde es so schreiben:[...]Uih. Die Lösung ist aber schön. Sie läßt sich irgendwie so richtig von oben nach unten lesen und ich raff sie auf anhieb.
perfekt zwar nicht, weil das while da nicht wirklich ausdrückt, wie lange die schleife zu laufen hat, aber das hat eh noch keine der lösungen geschafft, ohne nachher noch nen komplizierten hammer zu präsentieren.
-
Bashar: Huch, entschuligung. Das kommt eben davon, wenn man den halb modifizierten Code im Editorfenster nebenan für den echten hält ...
-
N'Abend!
1. Eine konkrete Aufgabestellung wäre nicht schlecht!
2. Was habt ihr bloß gegen Endlosschleifen, hm?
3. Gibt es gerade in der Softwareprogrammierung keine "richtige" und "falsche" Lösung! TMOO!
-
- alle anderen haben die Aufgabenstellung verstanden
- nix dagegen, aber wenn sie semantisch nicht paßt ...
- doch.
-
Original erstellt von Hexagon:
3. Gibt es gerade in der Softwareprogrammierung keine "richtige" und "falsche" Lösung!Mein Compiler will mich vom Gegenteil überzeugen.
-
Ja, die Sauberkeit von Nemesyzz' Lösung überzeugt.