Schleifen - Wieso keine Sicherheit?



  • Noch ne kleine Anmerkung: In C++11 ist dieses Verhalten explizit nicht mehr auf Schleifen begrenzt, sondern gilt beispielsweise auch bei endlosen rekursiven Aufrufen. Hab die entsprechende Stelle aber gerade nicht zur Hand.

    Edit: §1.10.24:

    The implementation may assume that any thread will eventually do one of the following:
    —terminate,
    —make a call to a library I/O function,
    —access or modify a volatile object, or
    —perform a synchronization operation or an atomic operation.
    [Note:This is intended to allow compiler transformations such as removal of empty loops, even when
    termination cannot be proven. —end note]



  • @Michael E.
    Ja, die ganze Geschichte mit "Programm/Funktion das nicht terminiert => UB => Compiler dürfen ganz wild Dinge wegoptimieren" hat ja durchaus für einige Diskussionen gesorgt.
    Das Argument des "pro" Lagers war dabei immer dass das bestimmte Optimierungen erlaubt die sonst nicht möglich wären.

    Was mich aber interessieren würde: gibt es da ein gutes Beispiel für eine Optimierung, die ohne diese Regel nicht möglich wäre, und wo auch etwas sinnvolles dabei rauskommt?

    Ich kann mir nämlich vorstellen dass bestimmte Optimierungen dadurch vielleicht einfacher werden, aber mir fällt nix ein wo es ohne diese Regel wirklich nicht möglich wäre.


  • Mod

    Die leere Endlosschleife wird schneller ausgeführt 🙂 .

    Um etwas sinnvoller zu werden: Gegeben ein Programmteil

    unsigned N;
    cin >> N;
    unsigned counter = 0;
    for (unsigned short i = 0; i < N; ++i)
     ++counter;
    // N im Folgenden nicht mehr benutzt.
    

    Könnte komplett durch

    unsigned counter;
    cin >> counter;
    

    ersetzt werden, wenn man weiß, dass die Schleife terminiert.

    Solche Fälle sollten sich leicht mehr (und sinnvoller) konstruieren lassen, wenn das Ergebnis einer Schleife für den Compiler berechenbar von den Kontrollvariablen abhängt (gar nicht so selten!), aber in einigen Ausnahmefällen die Schleife gar nicht abbrechen würde.



  • Wenn die Eingabe fehlschlägt, enthält die Variable einen undefinierten Wert.



  • 314159265358979 schrieb:

    Wenn die Eingabe fehlschlägt, enthält die Variable einen undefinierten Wert.

    War vorher auch so.



  • 314159265358979 schrieb:

    Wenn die Eingabe fehlschlägt, enthält die Variable einen undefinierten Wert.

    Für mich kam bisher ein Blockierskript für einzelne User nicht infrage. Wenn du jetzt allerdings jeden Beitrag von SeppJ kommentieren willst, weil du Unrecht hattest und das nicht einsehen willst, wanke ich sehr in meiner Haltung.



  • Ich hatte nicht Unrecht.



  • hustbaer schrieb:

    Ich kann mir nämlich vorstellen dass bestimmte Optimierungen dadurch vielleicht einfacher werden, aber mir fällt nix ein wo es ohne diese Regel wirklich nicht möglich wäre.

    Es ist einfacher, ein Programm auf Seiteneffekte zu testen, als auf Terminierung. Wenn der Compiler ersteres aber beweisen kann, darf er den entsprechenden Code eventuell trotzdem nicht wegoptimieren, wenn er Terminierung nicht zeigen kann.


  • Administrator

    hustbaer schrieb:

    Was mich aber interessieren würde: gibt es da ein gutes Beispiel für eine Optimierung, die ohne diese Regel nicht möglich wäre, und wo auch etwas sinnvolles dabei rauskommt?

    Ich hätte da eher eine andere Frage: Gibt es überhaupt sinnvolle Schleifen, welche in diese Kategorie fallen? Das Ganze scheint mir ein etwas theoretisches Konstrukt zu sein.

    Ich zweifle daher an diesen "weitreichenden Folgen", wie es SeppJ gesagt hat.

    Grüssli



  • (gast) schrieb:

    eine Warnung ausspucken sollte (hat mein g++ 4.6.1 selbst mit -Wall -pedantic nicht gemacht 😞 ). Dass die Abbruchbedingung hier nicht erreicht werden kann ist offensichtlich - trotzdem kein Grund overflows komplett zu verbieten. Das hier funktioniert nämlich:

    for(short i=32000; i<-32000 || i>0; ++i){}
    

    -Wextra ist gefragt.

    ethon@fleck:~$ gcc -Wall -Wextra test.cpp
    test.cpp: In Funktion »int main()«:
    test.cpp:10:22: Warnung: Vergleich ist durch beschränkten Wertebereich des Datentyps stets »wahr« [-Wtype-limits]



  • cvcv schrieb:

    for ( short int i = 0; i <= 32767; i++) 
         std::cout << i << "\n";
    

    Wieso setzt C++ am Ende des Schleifenkörpers nicht einfach ein conditional jump, der bei overflow-flag ausgeführt wird? Es wurde in C++ doch einige Sachen extra "sicherer" gemacht, zB strings nicht mehr anfällig für overflows's ... wieso wurde diese kleine Sache nicht implementiert?

    Weil der Überlauf bei Schleifenzählern wohl eines der Probleme ist, das am seltensten auftritt. Bei Berechnungen tritt manchmal ein Überlauf auf. Und bei Strings würde das garnichts bringen, ein Pufferüberlauf hat nichts mit einem Ganzzahlüberlauf zu tun und läßt sich nicht so abfangen.


Anmelden zum Antworten