private-bool-Variable wird falsch initialisiert



  • Hast du mal den Breakpoint in den Konstruktor gesetzt, ob da die Variablen stimmen? Evtl. wird der wert ja später geändert.
    Was macht denn dieses memset da? Damit sollte man sehr vorsichig sein.



  • Braunstein schrieb:

    Hast du mal den Breakpoint in den Konstruktor gesetzt, ob da die Variablen stimmen? [...]

    Ähmm... guter Hinweis! Ich habe gerade herausgefunden, das FormShow() => VOR <= dem Konstruktor aufgerufen wird... was soll das denn? 😕

    Braunstein schrieb:

    [...] Evtl. wird der wert ja später geändert.[...]

    Nein, wird er nicht.

    Braunstein schrieb:

    [...]Was macht denn dieses memset da? Damit sollte man sehr vorsichig sein.

    Das memset füllt ein

    unsigned char Array[1024];
    

    aus dem private-Bereich des Headers mit 0-Werten:

    memset(Array, 0x00, 1024);
    

    Warum soll ich damit vorsichtig sein?



  • Bei einem unsigned char-Array mag das memset ok sein. Problematisch wird es wenn man versucht damit Klassen zu initialisieren (hab ich hier im Forum schon gesehen).



  • Ok... und was ist jetzt mit FormShow() wird vor dem Konstruktor ausgeführt?

    Wie kann das sein. Ich kenne es so, dass der Konstruktor immer zuerst ausgeführt wird...!?!



  • Ja, das sollte normalerweise auch so sein. ABER vielleicht wird das Objekt nicht über den Konstruktor erzeugt, sondern mit irgendeiner Deserialisierung zusammengeschraubt, bei der das Objekt anders erzeugt wird. Würde mich auf jeden Fall nicht wundern.

    Zu dem Array:
    Ersetz das doch einfach durch einen std::vector<unsigned char>, dann hast du die gleiche Array Funktionalität und zusätzlich Bounds checking. Von den üblichen Vorteilen eines Vektors mal abgesehen. Das Füllen mit 0 passiert sogar implizit:

    std::vector<unsigned char> Buffer( 1024,0 );
    


  • Kolumbus schrieb:

    Ok... und was ist jetzt mit FormShow() wird vor dem Konstruktor ausgeführt?

    Wie kann das sein. Ich kenne es so, dass der Konstruktor immer zuerst ausgeführt wird...!?!

    Das passiert, wenn vor der Konstruktion TForm::Visible explizit auf true gesetzt wird.
    Du kannst in FormShow() einen Haltepunkt setzen und den Call-Stack benutzen, um herauszufinden, wer für den Aufruf verantwortlich ist (das dürfte die erste Funktion im Call-Stack, die nicht Teil der VCL ist, sein).

    Ein normaler Call-Stack für FormShow() sieht so aus:

    :00401BFC TForm1::FormShow(this=:00AC3750, Sender=:00AC3750)
    :00464803 Forms::TCustomForm::DoShow(Self=:00AC3750)
    :00469481 Forms::TCustomForm::CMShowingChanged(Self=:00AC3750, Message=:0012FC98)
    :0047F4D0 Controls::TControl::WndProc(Self=:00AC3750, Message=:0012FC98)
    :004840ED Controls::TWinControl::WndProc(Self=:00AC3750, Message=:0012FC98)
    :0046528A Forms::TCustomForm::WndProc(Self=:00AC3750, Message=:0012FC98)
    :0047F07D Controls::TControl::Perform(Self=:00AC3750, Msg=45081, WParam=0, LParam=0)
    :004835ED Controls::TWinControl::UpdateShowing(Self=:00AC3750)
    :0048367A Controls::TWinControl::UpdateControlState(Self=:00AC3750)
    :004864DA Controls::TWinControl::CMVisibleChanged(Self=:00AC3750, Message=:0012FED8)
    :0047F4D0 Controls::TControl::WndProc(Self=:00AC3750, Message=:0012FED8)
    :004840ED Controls::TWinControl::WndProc(Self=:00AC3750, Message=:0012FED8)
    :0046528A Forms::TCustomForm::WndProc(Self=:00AC3750, Message=:0012FED8)
    :0047F07D Controls::TControl::Perform(Self=:00AC3750, Msg=45067, WParam=1, LParam=0)
    :0047D579 Controls::TControl::SetVisible(Self=:00AC3750, Value=true)
    :00464B7E Forms::TCustomForm::SetVisible(Self=:00AC3750, Value=true)
    :0046E841 Forms::TApplication::Run(Self=:00AEBA40)
    :004017EF WinMain( =:00400000,  =NULL,  =:00141F33,  =9)
    :004dbe67 ; __startup
    


  • [quote="audacia]Das passiert, wenn vor der Konstruktion TForm::Visible explizit auf true gesetzt wird.
    Du kannst in FormShow() einen Haltepunkt setzen und den Call-Stack benutzen, um herauszufinden, wer für den Aufruf verantwortlich ist (das dürfte die erste Funktion im Call-Stack, die nicht Teil der VCL ist, sein).
    [/quote]

    Und auf welchem Objekt wird das aufgerufen? Wenn Visible nicht statisch ist (wovon ich ausgehe), dann sollte das Szenario niemals auftauchen, es sei denn, man greift auf ein nicht-initialisiertes Objekt zu und dann ist das Verhalten undefiniert. Oder unterliege ich da einem Denkfehler?



  • DocShoe schrieb:

    Und auf welchem Objekt wird das aufgerufen? Wenn Visible nicht statisch ist (wovon ich ausgehe), dann sollte das Szenario niemals auftauchen, es sei denn, man greift auf ein nicht-initialisiertes Objekt zu und dann ist das Verhalten undefiniert. Oder unterliege ich da einem Denkfehler?

    So dachte ich auch, und deshalb bin ich äußerst gespannt auf den Call-Stack 😉

    Es wäre z.B. denkbar, daß entweder ein Basisklassen- oder ein in der Initialisierungsliste aufgerufener Member-Konstruktor Visible auf true setzt.



  • Hallo,

    leider kann ich das erst am Montag prüfen, aber gespannt bin ich auch - besonders, weil das Ganze ja mit C++Builder3 funktioniert hat.

    Woher bekomme ich den Call-Stack, finde ich das allein? Muss ich dazu CodeGuard aktivieren? Der ist jetzt nämlich deaktiviert... Oder wozu ist GodeGuard gut?

    MfG



  • Kolumbus schrieb:

    Woher bekomme ich den Call-Stack, finde ich das allein?

    Mit der üblichen Portion Eigeninitiative sicher 😉
    (Du kannst ihn unter unter Ansicht|Debug-Fenster aktivieren; er dürfte aber im Debug-Layout bereits standardmäßig links oben erscheinen.)

    Kolumbus schrieb:

    Oder wozu ist GodeGuard gut?

    Überblick zu CodeGuard



  • Im BCB 5 und 6 gibt es die Eigenschaft TFrorm::OldCreateOrder. Wenn ja, ist die auf true oder false? Probier die gegenteilige Einstellung (sollte auf false stehen). Sollte zwar eigentlich nicht den Konstruktoraufruf beinflussen, aber wer weiß...

    Du kannst auch versuchen ein neues Projekt zu erstellen und die Units neu einzubinden. Hat bei mir etliche Probleme bei der Migrierung vom BCB5 zu BCH6 gelöst.

    Grüße Joe



  • Guten Morgen allerseits,

    Joe schrieb:

    Im BCB 5 und 6 gibt es die Eigenschaft TFrorm::OldCreateOrder. Wenn ja, ist die auf true oder false? Probier die gegenteilige Einstellung (sollte auf false stehen). Sollte zwar eigentlich nicht den Konstruktoraufruf beinflussen, aber wer weiß... [...]

    TFOrm::OldCreateOrder gibts im BDS2006 auch, es steht allerdings für alle Forms des Problemprojektes im Objektinspektor bereits auf true. Ich nehme an, dass BDS das automatisch gemacht hat, weil ich die Builder3-Projektgruppe einfach in BDS geöffnet habe, als ich das Projekt nach BDS übernommen habe. Die Hilfe des BDS sagt, OldCreateOrder wäre nur für die Ereignisse OnDestroy und OnCreate relevant, daher denke ich es hat mit meinem Problem nichts zu tun... wenn Alles nichts hilft, werde ich es natürlich testen - Danke für den Hinweis.

    Joe schrieb:

    [...] Du kannst auch versuchen ein neues Projekt zu erstellen und die Units neu einzubinden. Hat bei mir etliche Probleme bei der Migrierung vom BCB5 zu BCH6 gelöst.

    Auch ein guter Tip, den ich mir im Fall der Fälle später vornehmen werde - Danke. 🙂

    audacia schrieb:

    Kolumbus schrieb:

    Woher bekomme ich den Call-Stack, finde ich das allein?

    Mit der üblichen Portion Eigeninitiative sicher 😉
    (Du kannst ihn unter unter Ansicht|Debug-Fenster aktivieren; er dürfte aber im Debug-Layout bereits standardmäßig links oben erscheinen.)

    Danke, ich hab' ihn sofort gefunden... nennt sich "Aufruf-Stack"... muss man sowas übersetzen? ^^
    Hier das Ergebnis:

    Aufruf-Stack schrieb:

    :7c91e4f4 ntdll.KiFastSystemCallRet
    :7e369418 USER32.WaitMessage + 0xc
    :00490A13 Forms::TApplication::HandleMessage(Self=:00C64520)
    :00490C9F Forms::TApplication::Run(Self=:00C64520)
    :00401843 WinMain( =:00400000, =NULL, =:00141F19, =9)
    :005203fb ; __startup

    Mehr steht da nicht... 😞 Was kann ich / was könnt ihr jetzt mit dieser Info anfangen?

    [quote="audacia"]

    Kolumbus schrieb:

    Kolumbus schrieb:

    Oder wozu ist GodeGuard gut?

    Überblick zu CodeGuard

    Danke auch dafür. 🙂

    DocShoe schrieb:

    [...] Wenn Visible nicht statisch ist (wovon ich ausgehe), dann sollte das Szenario niemals auftauchen [...]

    Ist mit "statisch" in diesem Fall gemeint, dass es im Quelltext explizit geschrieben steht???

    EDIT: In Ermangelung anderer Ideen habe ich dann doch gleich mal TMainForm::OldCreateOrder auf false gesetzt und geschaut was passiert: Die Variablen aus der Initialisiererliste werden jetzt vorm TMainForm::FormShow() ordnungsgemäß initialisiert... allerdings verstehe ich die Zusammenhänge nicht!



  • Hintergrnde dazu weiß ich nicht. Ich hab mich nur daran erinnert, dass es seinerzeit massenweise Leute mit ähnlichen Problemem gab. Mein erster BCB war der 5er...



  • Ich setzte jetzt natürlich bei allen Forms des Projektes ::OldCreateOrder auf false, egal ob statisch oder dynamisch... richtig?

    Falls noch jemand Hintergrundinformationen dazu hat: immer her damit! 🙂

    Auf jeden Fall ein dickes Dankeschön an Alle Helfer! 👍



  • Kolumbus schrieb:

    Aufruf-Stack schrieb:

    :7c91e4f4 ntdll.KiFastSystemCallRet
    :7e369418 USER32.WaitMessage + 0xc
    :00490A13 Forms::TApplication::HandleMessage(Self=:00C64520)
    :00490C9F Forms::TApplication::Run(Self=:00C64520)
    :00401843 WinMain( =:00400000, =NULL, =:00141F19, =9)
    :005203fb ; __startup

    Mehr steht da nicht... 😞 Was kann ich / was könnt ihr jetzt mit dieser Info anfangen?

    Daraus ist zu entnehmen, daß eigentlich das Formular zu diesem Zeitpunkt schon initialisiert sein müßte, da in WinMain() TApplication::CreateForm() vor TApplication::Run() aufgerufen wird. Allerdings fehlt in deinem Call-Stack der Aufruf von TForm::DoShow - sicher, daß du den Breakpoint richtig gesetzt hast?
    Um die Ursache des Verhaltens aufzuklären, könntest du in den aufrufenden Funktionen Haltepunkte setzen - wenn es dich noch interessiert 😉

    Kolumbus schrieb:

    EDIT: In Ermangelung anderer Ideen habe ich dann doch gleich mal TMainForm::OldCreateOrder auf false gesetzt und geschaut was passiert: Die Variablen aus der Initialisiererliste werden jetzt vorm TMainForm::FormShow() ordnungsgemäß initialisiert... allerdings verstehe ich die Zusammenhänge nicht!

    Warum sich das auch auf OnShow auwirkt, verstehe ich nicht so recht - mein C++Builder 2006 führt OnShow, wie erwartet unabhängig von OldCreateOrder, erst nach der Konstruktion aus.

    Kolumbus schrieb:

    Ich setzte jetzt natürlich bei allen Forms des Projektes ::OldCreateOrder auf false, egal ob statisch oder dynamisch... richtig?

    Ja, es sollte nicht schaden - zumal man in C++Builder OnCreate() und OnDestroy() ohnehin nicht benutzen sollte.



  • Kolumbus schrieb:

    Ist mit "statisch" in diesem Fall gemeint, dass es im Quelltext explizit geschrieben steht???

    Nein, mit statisch meine ich, dass das Visible Attribut als statische Variable (oder Klassenvariable) in der Klasse TForm deklariert wurde. War aber eher eine rehtorische Frage, denn das würde keinen Sinn machen. Wenn es so wäre könnte man solche Schweinereien zaubern, in denen Zugriff auf statische Variablen durch nicht-initialisierte Zeiger legitim ist (und damit auch vor der Konstruktion erlaubt sind).

    struct Test
    {
       static bool Visible;
    };
    
    // Initialisierung der statischen Variable
    static Test::Visible = false;
    
    int main()
    {
       // nicht initialisierter Zeiger auf ein Objekt vom Typ test
       Test* pTest;   
    
       // erlaubt, obwohl pTest ins Nirvana zeigt
       pTest->Visible = true;
    }
    

    Wer sowas allerdings tatsächlich macht gehört erschossen oder in die Klapse.

    /Edit akari : Tags korrigiert.



  • Verdammt, Tags verwechselt... muss mich vielleicht doch mal irgendwann hier regsitrieren.



  • Verdammt, rhetorisch falsch geschrieben... los, Akari! 😉



  • Hallo

    Der [spelling]-Tag kann automatisch den einbezogenen Text in Bezug auf Rechtschreibung korrigieren... aber der ist noch im Beta-Status 😉

    bis bald
    akari



  • audacia schrieb:

    [...]Allerdings fehlt in deinem Call-Stack der Aufruf von TForm::DoShow - sicher, daß du den Breakpoint richtig gesetzt hast? [...]

    Entschuldigung, mein Fehler! Ich hatte den Call-Stack ermittelt, indem ich das Projekt gestartet und dann im BDS auf Pause geklickt habe... 🕶 Hier der Call-Stack mit TForm::OldCreateOrder auf true (Variablen aus Initialisiererliste des Konstruktors nicht initialisiert) und Haltepunkt an der 1. Anweisung in der TForm::FormShow()-Methode:

    Aufruf-Stack schrieb:

    :00401C11 TFormMain::FormShow(this=:00C3ED60, Sender=:00C3ED60)
    :0048B5A3 Forms::TCustomForm::DoShow(Self=:00C3ED60)
    :0049017D Forms::TCustomForm::CMShowingChanged(Self=:00C3ED60, Message=:0012FAD0)
    :004A5830 Controls::TControl::WndProc(Self=:00C3ED60, Message=:0012FAD0)
    :004AA53A Controls::TWinControl::WndProc(Self=:00C3ED60, Message=:0012FAD0)
    :0048C02A Forms::TCustomForm::WndProc(Self=:00C3ED60, Message=:0012FAD0)
    :004A53DD Controls::TControl::Perform(Self=:00C3ED60, Msg=45081, WParam=0, LParam=0)
    :004A9A69 Controls::TWinControl::UpdateShowing(Self=:00C3ED60)
    :004A9AF6 Controls::TWinControl::UpdateControlState(Self=:00C3ED60)
    :004AC926 Controls::TWinControl::CMVisibleChanged(Self=:00C3ED60, Message=:0012FD10)
    :004A5830 Controls::TControl::WndProc(Self=:00C3ED60, Message=:0012FD10)
    :004AA53A Controls::TWinControl::WndProc(Self=:00C3ED60, Message=:0012FD10)
    :0048C02A Forms::TCustomForm::WndProc(Self=:00C3ED60, Message=:0012FD10)
    :004A53DD Controls::TControl::Perform(Self=:00C3ED60, Msg=45067, WParam=1, LParam=0)
    :004A3939 Controls::TControl::SetVisible(Self=:00C3ED60, Value=true)
    :0048B91E Forms::TCustomForm::SetVisible(Self=:00C3ED60, Value=true)
    :0048ABE2 Forms::TCustomForm::DoCreate(Self=:00C3ED60)
    :0048A768 Forms::TCustomForm::Create(Self=:00C3ED60, AOwner=:00C64520, ...)
    :00401B90 Forms::TForm::TForm(this=:00C3ED60, AOwner=:00C64520)
    :00401A50 TFormMain::TFormMain(this=:00C3ED60, Owner=:00C64520)
    :00495373 Forms::TApplication::CreateForm(Self=:00C64520, InstanceClass=:0052F250, Reference=:00543880)
    :00401837 WinMain( =:00400000, =NULL, =:00141F19, =9)
    :00524b73 ; __startup

    Wenn ich das richtig sehe, kommt bei diesem Stack-Auszug das Show() vor dem Create()!?
    Wie gehen wir jetzt vor, um dem Problem weiter auf den Grund zu gehen?

    audacia schrieb:

    [...] zumal man in C++Builder OnCreate() und OnDestroy() ohnehin nicht benutzen sollte.

    Genau, das mache ich auch nicht; das habt ihr mir schon ganz zu Anfang beigebracht => 🙂 (klick' den Smilie)

    @_DocShoe_: Danke für die Erklärung. Solch' umständliche Schweinereien mache ich beim Programmieren (noch) nicht... Mir reichen weniger komplizierte Konstrukte, um mich selbst zu verwirren... 😉

    akari schrieb:

    Der [spelling]-Tag kann automatisch den einbezogenen Text in Bezug auf Rechtschreibung korrigieren... aber der ist noch im Beta-Status 😉

    [spelling]-Tag 😮 Erkennt der auch Dialekte? Die deutsche Sprache wird ja schließlich von vielerlei fiesen Mutationen heimgesucht... 🤡


Anmelden zum Antworten