Bug in C++ Builder 5 - Ungültige Gleitkommaoperation?



  • Hallo zusammen,

    ich verzweifle noch. Ich habe ein großes Projekt mit ca. 20 Formularen und einer exe die 8 MB gross ist.
    In letzter Zeit häuft sich bei mir das Problem, das mein BCB 5 das Projekt zwar compiliert, aber beim Start in der ersten FormActivate Prozedur an einem Codestück aussteigt das so aussieht:

    verh = laenge * (int)(FAKTORX / 100.0);
    

    Die Meldung lautet: "Ungültige Gleitkommaoperation"

    verh, laenge sind Integer;
    FAKTORX ist ein double der direkt drüber gebildet wird und so ca. 40-80 sein sollte.

    Wenn ich mit dem Debugger mir FAKTORX betrachte hat er den Wert 12 * 10^(-243) (also 0,0000000...12).
    Das wird wohl das Problem verursachen.
    Aber ich habe an dieser Stelle im Code schon ewig nichts verändert.

    Der Knalle ist, wenn ich alle .obj, .tds Files weglösche und das ganze Projekt aktualisiere (was 10 Min. dauert ;-() dann läuft es ohne das ich irgendwas am Code mache.
    Wenn ich dann was verändere geht es eine Weile und so nach ein paar Compilierungen irgendwann tritt der Fehler wieder auf.

    Habt ihr sowas schon mal erlebt? Könnte das Problem irgendeine große Puffer-Datei sein?

    Gruß
    jf_stgt



  • Gibt es denn eine Möglichkeit, wo FAKTORX nicht initialisiert wird? Das wäre undefiniertes Verhalten, hat bis eben geklappt, jetzt aber eben nicht mehr.



  • witte schrieb:

    Gibt es denn eine Möglichkeit, wo FAKTORX nicht initialisiert wird? Das wäre undefiniertes Verhalten, hat bis eben geklappt, jetzt aber eben nicht mehr.

    FAKTORX ist eine globale Variable und wird in der gleichen Funktion initialisiert (ein paar Zeilen davor).
    Mein Verdacht ist eher, dass irgendeine andere Variable die auch global ist FAKTORX überschreibt (afgrund eines Bugs).

    Der Witz ist ja, dass nach einem kompletten Neucompilieren aller Units alles wieder funktioniert.



  • Hallo

    Das Problem mit dem Neukompilieren deutet aber wirklich auf undefiniertes Verhalten hin, was bei deiner Beschreibung nur dann auftreten könnte wenn die Initialisierung von FAKTORX zwar vorhanden, aber trotzdem nicht vor der Berechnung ausgeführt wird (Bedingung nicht erfüllt?)

    Auf jedenfall ein weiteres Beispiel warum man globale Variablen vermeiden sollte. Immerhin scheinst du selber nicht mal nachprüfen zu können wann und ob initialisiert wird (deine Zahlenangabe aus dem ersten Post deutet darauf hin das die Zahl nicht initialisiert wird) oder ob die Variable lokal verdeckt wird...

    bis bald
    akari



  • jf_stgt schrieb:

    Mein Verdacht ist eher, dass irgendeine andere Variable die auch global ist FAKTORX überschreibt (afgrund eines Bugs)

    WTF?
    Würde wahrscheinlich dem Fehlerbild entsprechen, bei einer Neukompilierung würde dann die Anordnung der Variablen anders sein. Und warum nimmst Du den Bug dann nicht raus? Offensichtlich zeigst sich hier die Fehleranfälligkeit globaler Variablen. Warum schützt Du diese nicht mit Getter/Setter in einer geeigneten Klasse? Dann bräuchtest Du jetzt nur ein Breakpoint auf den Setter setzen, loslaufen lassen, abwarten, fertig.



  • Ich bin auch kein Freund von globalen Variablen aber manchmal sind diese einfach sehr geschickt.

    witte schrieb:

    Warum schützt Du diese nicht mit Getter/Setter in einer geeigneten Klasse? Dann bräuchtest Du jetzt nur ein Breakpoint auf den Setter setzen, loslaufen lassen, abwarten, fertig.

    Also ich kann ja den Breakpoint auch auf das FAKTORX = ... setzen. Dann sehe ich ja auch, ob die Variable vor dem Lesezugriff (der zum Crash führt) überhaupt gesetzt ist. Und ja, sie ist gesetzt!

    akari schrieb:

    Das Problem mit dem Neukompilieren deutet aber wirklich auf undefiniertes Verhalten hin, was bei deiner Beschreibung nur dann auftreten könnte wenn die Initialisierung von FAKTORX zwar vorhanden, aber trotzdem nicht vor der Berechnung ausgeführt wird (Bedingung nicht erfüllt?)

    Ein Arbeitsspeicherproblem könnte es nicht sein, oder? Wie gesagt, die globale Variable habe ich eigentlich gar nicht verändert.

    😕 😕 😕



  • Hallo

    Naja für uns hier ist es natürlich nicht komplett ausschließbar, das dein Arbeitspeicher einen Hardwarefehler hat. Der würde sich aber kaum so gezielt äußern, da müßten nach hinreichend langer Zeit auch mal andere Programme davopn betroffen sein.

    Das der Fehler in deinem Code ist halte ich für wesentlich wahrscheinlicher.

    bis bald
    akari



  • jf_stgt schrieb:

    Ich bin auch kein Freund von globalen Variablen aber manchmal sind diese einfach sehr geschickt.

    Ich wüsste keinen Fall in denen ich eine globale Variable als "geschickt" bezeichnen könnte. Selbst in dem Fall das ich Tatsächlich mal Daten global haben müsste (ich erinnere mich nicht es in der Vergangenheit mal wirklich gebraucht zu haben), gibt es eine bessere Alternative (mit klarer Definition des Initialisierungszeitpunktes):

    int& GlobalerWert()
    {
        static int = 0;
        return int;
    }
    

    Aber selbst das Konstrukt habe ich bislang kaum verwendet.

    cu André



  • akari schrieb:

    Naja für uns hier ist es natürlich nicht komplett ausschließbar, das dein Arbeitspeicher einen Hardwarefehler hat. Der würde sich aber kaum so gezielt äußern, da müßten nach hinreichend langer Zeit auch mal andere Programme davopn betroffen sein.

    Ne, an einen Hardwarefehler glaube ich auch keinesfalls.

    Eher, dass irgendein Array über seine Grenzen gefüllt wird oder (und um das ging es mir hier), dass Borland hier irgendwas irgendwo hinschreibt. Oder ist dies unwahrscheinlich?
    Wenn es ein Programmierfehler von mir ist und wirklich hier Grenzen überschrieben werden - wie solle ich den finden?



  • Hallo

    Es ist natürlich auch möglich das irgendein anderer deiner Speicherzugriffe (wie du schon selbst sagst Array oder Pointer sinf potentielle Kandidaten) fälschicherweise den Speicher überschreibt. Das könnte aber dann nur zwischen dem letzten Schreibzugriff und dem fehlerauslösenden Lesezugriff auf FAKTORX passieren. Vielleicht hilft dir ja diese Einschränkung.

    Aber auch hier halte ich es sehr viel wahrscheinlicher das die Ursache in deinem Code liegt als im Code von der VCL, im Borland-Compiler oder gar in der Speicherverwaltung von Windows.

    bis bald
    akari



  • Könnte Dir eigentlich ein Watchpoint helfen? Das er anhält wenn der Speicher überschrieben wird? Ich arbeite leider zu selten mit dieser Technik...



  • witte schrieb:

    Könnte Dir eigentlich ein Watchpoint helfen? Das er anhält wenn der Speicher überschrieben wird? Ich arbeite leider zu selten mit dieser Technik...

    Ich weiß gar nicht ob das mit dem C++ Builder überhaupt geht???! Ich habe auf Anhieb leider nichts gefunden.

    Was witziges was schon auf so einen Speicherfehler hindeutet:

    int abc = 12 * FAKTORX; // (1)
    int def = 9 * FAKTORX; // (2)
    

    In Zeile 1 steht laut Breakpoint FAKTORX auf 0 und die Zeile läuft auch.
    In Zeile 2 steht laut Breakpoint FAKTORX immer noch auf 0 (klar!) aber wenn ich F8/F7 drücke, knallt es mit bekannter Fehlermeldung.



  • Ich kanns mir zwar net erklären, aber ich habe das

    float FAKTORX
    

    in ein

    int FAKTORX
    

    umbenannt und in meinem Code ein Faktor 100 miteingerechnet (damit ich auf die Genauigkeit komme die ich brauche) und nun geht es.



  • jf_stgt schrieb:

    Ich weiß gar nicht ob das mit dem C++ Builder überhaupt geht???!

    Natürlich geht das, nur heißt das da "Datenhaltepunkt".



  • audacia schrieb:

    jf_stgt schrieb:

    Ich weiß gar nicht ob das mit dem C++ Builder überhaupt geht???!

    Natürlich geht das, nur heißt das da "Datenhaltepunkt".

    Aha. Klingt gut. Und wo finde ich den?



  • Start|Haltepunkt hinzufügen...|Datenhaltepunkt?



  • Hallo zusammen,

    also es ist echt zum verzweifeln.
    Ich habe so langsam alles versucht.
    Die globalen Variablen habe ich alle zu Klassenvariablen meiner Hauptform gemacht und sie in den anderen Formen mit hauptform->variable angesprochen.
    Auch der Datenhaltepunkt hat nichts gebracht.

    Das Problem tritt immer noch auf!
    Es hängt aber mit double oder float Variablen zusammen und es ist nicht immer FAKTORX. Manchmal läuft er nach dem Compilieren am "FaktorX Problem vorbei" und bringt den Fehler in einer ganz anderen Form.
    *.ob, *.tds und sonstige Dateien habe ich auch weggelöscht.

    Wie gesagt, das sonderbare ist, dass es nach dem kompletten Rebuild geht, aber wenn ich dann nur eine Unterform ändere und mit F9 kompiliere, steigt er mir aus.

    Habt ihr noch ein Tipp?

    Viele Grüße
    jf_stgt



  • Du könntest versuchen ein Minimalprojekt zu erstellen, bei dem der Fehler reproduzierbar ist. Dabei würdest Du die Abhängigkeiten dieses Fehlers sehen. Dann könntest Du ihn evtl. hier posten.



  • Wie schon erwähnt wird es wohl irgendwo in deinem Code zu undefinierten Verhalten kommen der sich dann später als Fehler ausdrückt. Versuche mal einfach alles mögliche auszukommentieren, bis der Fehler nicht mehr auftritt. Dann füge nach und nach wieder das auskommentierte ein. Dann wirst du schon sehen woran es wirklich liegt.



  • witte schrieb:

    Du könntest versuchen ein Minimalprojekt zu erstellen, bei dem der Fehler reproduzierbar ist. Dabei würdest Du die Abhängigkeiten dieses Fehlers sehen. Dann könntest Du ihn evtl. hier posten.

    Dies ist etwas schwierig, da ich wirklich viele Formulare habe und da nicht einfach Formulare rauslösen kann da die ja zum Teil aufeinander aufbauen.
    Aber ich werde es versuchen.

    Braunstein schrieb:

    Wie schon erwähnt wird es wohl irgendwo in deinem Code zu undefinierten Verhalten kommen der sich dann später als Fehler ausdrückt. Versuche mal einfach alles mögliche auszukommentieren, bis der Fehler nicht mehr auftritt. Dann füge nach und nach wieder das auskommentierte ein. Dann wirst du schon sehen woran es wirklich liegt.

    Das mit dem Auskommentieren ist eine gute Idee (könnte von mir sein). Ich werde mal alles auskommentieren was ich in den letzten 1-2 Wochen geändert habe.
    Das dumme ist, das der Fehler nicht immer auftritt.
    aber man könnte natürlich warten, bis der Fehler kommt - dann auskommentieren. Form für Form. Und wenn er weg ist, ists klar woher es kommt, oder?

    Eine maximale Größe einer (verabeitbaren) Header/C++ Datei gibt es nicht, oder? Ich habe nämlich v.a. in einer Form viele neue Labels eingefügt. Die sind dann ja im Header und dieser Header wird dann im Hauptform eingebunden (incude).

    Gruß
    jf_stgt


Anmelden zum Antworten