Ich habe hier grade ein komisches Problem über "Ferndebugging" lösen dürfen (also mehrfaches Abändern des Codes mit anschließender Zusendung des MadExcept-Bugreports.
Ich hoffe, ich breche den Code nicht zu stark herunter. Folgendes.
Im OnCreate der Form erstelle ich ein paar Objekte.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.FormCreate(Sender: TObject); begin Foo := TFoo.Create; Bar := TBar.Create; Bar.foo := Foo; end; |
Diese Objekte brauche ich dann z.B., um passend auf das Resize eines Panels auf der Form1 zu reagieren.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.Panel1Resize(Sender: TObject); begin if Foo.Bool1 then Foo.DoSomething; end; |
Das finde ich schonmal merkwürdig, dass das Panel.OnResize aufgerufen wird, bevor das FormCreate fertig ist. Aber gut. Noch seltsamer wird es dann beim nächsten Panel-Resize:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.Panel2Resize(Sender: TObject); begin if Bar.Bool2 then Bar.DoStuff; end;
procedure TBar.DoStuff; begin if foo.Bool3 then DoSomeWork; end; |
Abhilfe ist wieder die gleiche.
Ich frage mich nun, wie es passieren kann, dass Zugriff auf Foo fehlschlägt, aber der Zugriff auf Bar, das nach Foo erzeugt wird, erst einmal keine Fehlermeldung verursacht. Und das ganze natürlich nur auf einem System (oder einigen?). Bei mir unter Win10, 64 Bit läuft das durch. Der gemeldete Fall war wohl ein Windows 10 (32 Bit) auf einem Tablet-PC.
Klingt nach einem klassischen Race-Condition-Bug, aber wie kommt der hier zustande? Macht die VCL hier auf einmal Multithreading und arbeitet schonmal weiter, während das Foo.Create und die Variablenzuweisung noch läuft?
Und wie kann ich das sauber verhindern? Beim Start des FormCreate alle Resize-Handler auf Nil setzen und am Ende wieder passend? Oder muss ich im Form-Designer schon die Resize-Handler austragen, und darf sie nur manuell nach dem Create setzen?
Hat der wer einen Denkanstoß für mich?
We are, we were and will not be.