goto is evil
-
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.
-
Find ich auch gut. Danke
-
Hier ist mein Vorschlag:
bool bCycle = false; do { rc = slow_syscall(); if ( rc < 0 ) { bCycle = errno == EINTR; if ( bCycle == true ) { bCycle = restart; } else { perror("slow_syscall"); exit(EXIT_FAILURE); } } } while ( bCycle == true );
-
Original erstellt von Finten:
**Hier ist mein Vorschlag:bool bCycle = false; do { rc = slow_syscall(); if ( rc < 0 ) { bCycle = errno == EINTR; if ( bCycle == true ) { bCycle = restart; } else { perror("slow_syscall"); exit(EXIT_FAILURE); } } } while ( bCycle == true );
**
hmm.... also ich würde das noch ein wenig ändern (nur vom "aussehen") :
bool bCycle = false; do { rc = slow_syscall(); if(rc < 0) { //bCycle = errno == EINTR; if(bCycle = errno == EINTR) bCycle = restart; else { perror("slow_syscall"); exit(EXIT_FAILURE); } } } while(bCycle);
-
Mit einer Hilfsvariable wäre das auch noch möglich ohne das if - sieht aber mmn nich so schön aus...
bool cont = true; while(slow_syscall() < 0 && cont) { cont = restart; if(errno != EINTR) { perror("slow_syscall"); exit(EXIT_FAILURE); } }
-
Jo, Nemesyzz' Lösung ist die beste.
-
Ich würd beim goto bleiben.