Glaube ich erst, wenn ich es sehe. Wollte mir gestern schon jemand weismachen, und dann war es eine falsch formulierte Schleifenbedingung. Klar; ich hatte ja selber schon einen Bug, dass ein Register fälschlicherweise als ungenutzt eingestuft wurde und futtsch war – aber komplette Textstellen? Niemals, jedenfalls nicht mit GCC oder Visual C++ nach 6.BeRsErKeR hat geschrieben:Wobei ich auch schon die Erfahrung gemacht habe, dass Compiler mitunter sehr komische Sachen machen, z.B. Codeteile wegoptimieren, weil sie denken dass sie nicht gebraucht werden und wenn man sie dann nutzen will knallts.
Return value im Falle von Try-Catch
- Krishty
- Establishment
- Beiträge: 8343
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Return value im Falle von Try-Catch
Re: Return value im Falle von Try-Catch
Glaub mir wir hatten viel Freude auf Arbeit mit dem gcc 4.4.X. Die Optimierung hat mitunter sehr lustige Dinge getan. Und das Wegoptimieren konnte man auch gut im ASM angucken. Die Codeteile waren tatsächlich weg.Krishty hat geschrieben:Glaube ich erst, wenn ich es sehe. Wollte mir gestern schon jemand weismachen, und dann war es eine falsch formulierte Schleifenbedingung. Klar; ich hatte ja selber schon einen Bug, dass ein Register fälschlicherweise als ungenutzt eingestuft wurde und futtsch war – aber komplette Textstellen? Niemals, jedenfalls nicht mit GCC oder Visual C++ nach 6.BeRsErKeR hat geschrieben:Wobei ich auch schon die Erfahrung gemacht habe, dass Compiler mitunter sehr komische Sachen machen, z.B. Codeteile wegoptimieren, weil sie denken dass sie nicht gebraucht werden und wenn man sie dann nutzen will knallts.
Noch schöner war:
Code: Alles auswählen
float f = 0.33f * (rand() % 10000);
printf("out: %0.6f\n", f);
printf("out: %0.6f\n", f);
In unserem Projekt steht nun ein Präprozessor-Makro, welches einen #error schmeißt sofern man eine 4.4.X Version von gcc nutzt und die Optimierung aktiv ist.
Ohne Input kein Output.
- Krishty
- Establishment
- Beiträge: 8343
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Return value im Falle von Try-Catch
Aua. Ist ja grauenhaft! Habe auch keine Vorstellung, wie sowas passieren kann.
Re: Return value im Falle von Try-Catch
Das Problem an der printf-Sache war, dass wir eigentlich die Übertragung von floats im BE-Format mit spezieller Codierung realisieren wollten und dann den Wert auf beiden Seiten (eine Seite Sun -> BE, andere Seite Ubuntu -> LE) per printf ausgegeben haben. Wir haben 2 Tage gesucht und dachten die Übertragung sei fehlerhaft. Dann haben wir gemerkt, dass sich der Wert bereits nach dem ersten printf auf der Senderseite ändert. Gleiches passierte im Übrigen auch bei std::cout. Anfangs dachten wir, dass die vaargs vom printf irgendwas kaputt hauen, aber als dann auch std::cout in die Knie ging kannten wir eigentlich schon die Lösung: volatile. :D
Ohne Input kein Output.
- Krishty
- Establishment
- Beiträge: 8343
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Return value im Falle von Try-Catch
Das kann ja wieder was anderes sein – dass tan(x) != tan(x) ist (weil die CPU den ersten Wert in eine float oder double zurückschreibt bevor sie den zweiten ausrechnet, und dabei vom 80-Bit-Zwischenergebnis 16 oder 48 Bits verloren gehen während der Zweite noch mit voller Präzision im FPU-Revolver liegt), ist allgemein bekannt und zulässig. Bei printf() werden auch vor der Übergabe alle Operanden zu 64 Bits konvertiert; [bzzzz ich habe ganz überlesen, dass es mit cout auch nicht ging] es könnte also tatsächlich der Fehler sein, dass durch globale Optimierungen einige Zahlen auf den Stapelspeicher gespült werden während andere in der FPU bleiben.
Da oben sah es aber aus, als hätte der Compiler nicht kapiert, dass rand() eine Wirkung hat und er deshalb den Funktionsaufruf nicht duplizieren darf. Das wäre ein Kaliber, wodurch der ganze Compiler unbrauchbar würde.
Da oben sah es aber aus, als hätte der Compiler nicht kapiert, dass rand() eine Wirkung hat und er deshalb den Funktionsaufruf nicht duplizieren darf. Das wäre ein Kaliber, wodurch der ganze Compiler unbrauchbar würde.
Re: Return value im Falle von Try-Catch
Ja alle diese Fälle haben wir auch vermutet. Letztlich handelt es sich scheinbar wirklich um ersteren Sachverhalt. Uns fiel recht schnell auf, dass der Wert nach dem ersten printf (also bei weiteren Ausgaben) genau dem Wert entspricht, den man erhält, wenn man den float-Wert vorher in einen double castet (bei double gab es übrigens keine Abweichungen). Es war auch immer so, dass nur die erste Ausgabe fehlerhaft war.
Das merkwürdige ist halt, dass bei der Übergabe von f an printf oder cout eigentlich eine Kopie übergeben werden müsste. Somit kann sich f theoretisch nicht ändern und jeder printf-Aufruf sollte identisch sein. Allerdings hatten wir dann auch schnell die FPU im Verdacht, die zusammen mit der Optimierung für die Abweichungen sorgt. Auch waren die Abweichungen zu gering um nicht von Rundungs- bzw. Umwandlungsfehlern auszugehen.
Prinzipiell finde ich es aber schon unglücklich, wenn ein und derselbe Funktionsaufruf unterschiedliche Outputs liefert, jedenfalls bei Funktionen, die nichts anderes erwarten lassen. Von mir aus kann er den Wert ja in einen double casten, allerdings sollte der Output immer identisch sein. Auch beim 1. Aufruf.
Merkwürdig war auch, dass ein cout-Aufruf den ersten printf-Aufruf gefixt hat und umgekehrt.
Das merkwürdige ist halt, dass bei der Übergabe von f an printf oder cout eigentlich eine Kopie übergeben werden müsste. Somit kann sich f theoretisch nicht ändern und jeder printf-Aufruf sollte identisch sein. Allerdings hatten wir dann auch schnell die FPU im Verdacht, die zusammen mit der Optimierung für die Abweichungen sorgt. Auch waren die Abweichungen zu gering um nicht von Rundungs- bzw. Umwandlungsfehlern auszugehen.
Prinzipiell finde ich es aber schon unglücklich, wenn ein und derselbe Funktionsaufruf unterschiedliche Outputs liefert, jedenfalls bei Funktionen, die nichts anderes erwarten lassen. Von mir aus kann er den Wert ja in einen double casten, allerdings sollte der Output immer identisch sein. Auch beim 1. Aufruf.
Merkwürdig war auch, dass ein cout-Aufruf den ersten printf-Aufruf gefixt hat und umgekehrt.
Ohne Input kein Output.
- Krishty
- Establishment
- Beiträge: 8343
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Return value im Falle von Try-Catch
printf() castet, wie gesagt, zu 64 Bits und bei cout ist es oft so, dass man der Wartbarkeit halber ein- und dieselbe Routine benutzt, um sowohl float als auch double in einen String zu schreiben. Konvertiert wird die Zahl also (leider) immer irgendwie. Ziemlich ärgerlich, wenn dann sowas passiert.BeRsErKeR hat geschrieben:Das merkwürdige ist halt, dass bei der Übergabe von f an printf oder cout eigentlich eine Kopie übergeben werden müsste. Somit kann sich f theoretisch nicht ändern und jeder printf-Aufruf sollte identisch sein. Allerdings hatten wir dann auch schnell die FPU im Verdacht, die zusammen mit der Optimierung für die Abweichungen sorgt. Auch waren die Abweichungen zu gering um nicht von Rundungs- bzw. Umwandlungsfehlern auszugehen.
Re: Return value im Falle von Try-Catch
Im gcc 4.5.X war der Fehler übrigens verschwunden. Es war also definitiv ein compilerspezifischer Bug in der Optimierung. Das Schlimme an solchen Bugs ist halt dass man einen Haufen Zeit sinnlos verschwenden muss und kurz davor ist den kompletten Code umzuschreiben.
Ohne Input kein Output.