Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Programmabsturz! Warum? (https://www.delphipraxis.net/63586-programmabsturz-warum.html)

m_junglas 20. Feb 2006 23:28


Programmabsturz! Warum?
 
Hallo,

ich habe ein Problem, was ich nach Tagen nicht einkreisen konnte. Vielleicht hat jemand eine Lösung?
Ich habe eine DLL programmiert, die ein Formular öffnet. In einem StringGrid habe ich Elemente drin, die bei der Selektion eine Datenbankabfrage starten. Diese habe ich (damit da nichts blockiert) in einen Thread ausgelagert.
Im OnTerminate-Event stelle ich dann das Ergebnis dar.
Der Thread wird dann auch entfernt.

Klappt alles bestens und fehlerfrei... meistens! Je nach Laune stürzt das Programm nach ein paar Klicks auf das StringGrid ab! Und es ist ein satter Absturz:
Delphi-Debugger sagt "Access Violation at $..." aber ohne einen Fehlerort (Source-Zeile).
Ohne Delphi-Umgebung erscheint ein "unbekannter Softwarefehler".
Offensichtlich werden dann die Objekte in meinem Programm noch nichteinmal mehr über den Destructor gelöscht, wie ich sehen kann.

Nach langen Tests habe ich festgestellt, dass das Programm ZWISCHEN meinen Ereignisroutinen abschmiert. Da bin ich jetzt ziemlich machlos!

Kennt jemand ein solches Problem? Was könnte das sein? Bitte helft mir!

Da das ganze Programm schon relativ gross geworden ist ist es schwierig einen Codeausschnitt zu bringen, aber kann gerne auf Anfrage Details bringen.
Irgendwie grummelt in meinem Hinterkopf die üblichen Probleme mit verschiedenen Speichermanagern Prog/DLL, owner und parent und was weiss ich.
Muss ich auch innerhalb vopn DLLs mit stdcall arbeiten?

Danke schonmal!
/\/\arcus

p.s. benutze Delphi 6 unter Win XP.

Luckie 20. Feb 2006 23:33

Re: Programmabsturz! Warum?
 
Hast du den Kommentar beachtet, den dir Delphi erzeugt, wenn du eine DLL mit dem DLL-Wizard erzeugst? Desweiteren ist die VCL nicht threadsafe. Werden alle Zugriffe auf visuelle VCL Elemte in einer Synchronize-Methode durchgeführt? Überprüf das mal alles und berichte. Ansonsten ist da schwer zu helfen ohne Code gesehen zu haben.

m_junglas 21. Feb 2006 22:27

Re: Programmabsturz! Warum?
 
Hallo nochmal,

den Hinweistext kenne ich. Darin geht es ja um Parameterübergabe aus und in DLLs. In meinem Problem bleibe ich aber eigentlich komplett innerhalb der DLL (Fenster wird in DLL erzeugt, in Ereignisroutine dann der Thread).
Vom Thread aus greife ich auch überhaupt nicht auf die VCL zu.

Ich kann sogar den Thread so zusammenstreichen, dass er nur ein paar thread-lokale Variablen beschreibt und sich gleich wieder beendet. Trotzdem Absturz - wieder NACH OnTerminate() und NACH dem Destruktor des Threads.

Offenbar ist da schon bei der Erzeugung des Threads was faul.
Ich werde morgen mal alles aus dem großen Programm herausextrahieren und versuchen das Problem freizulegen. :gruebel:
Ich dachte mir nur, dass jemand hier zufällig schonmal sowas hatte und mir gleich meine Fehler um die Ohren hauen könnte. :wink:
Wenn alles soweit freigelegt ist und ich nichts finde melde ich mich vielleicht präziser zurück.

Trotzdem hier mal Ausschnitte, die den Thread betreffen:

Erzeugung im OnCreate() des Fensters:
Delphi-Quellcode:
IdentListThread := IdentFillThrd.Create(true); // suspendiert erzeugen
IdentListThread.FreeOnTerminate := false;
IdentListThread.OnTerminate := IDlisteFertig;
IdentListThread.Resume;
Die Funktion, die beim OnTerminate-Ereignis ausgeführt wird macht etwa folgendes:
Delphi-Quellcode:
StatusBar.Panels[0].Text := 'Identnummernliste steht bereit';
{ andere Dinge sind auskommentiert, Absturz erfolgt dennoch }
IdentListThread.Free;
IdentListThread := nil;

Wie gesagt: der Code tut völlig was ich will. Keine falschen Ergebnisse, keine direkten Fehler bei meinem eigenen Code. Nur eben gleich darauf... :wall:

Aber jetzt erstmal 'n Bierchen! Weia... wenn das nicht auch mal ein Absturz gibt...
Tschüss
/\/\arcus

Matze 21. Feb 2006 22:34

Re: Programmabsturz! Warum?
 
Zitat:

Zitat von m_junglas
Die Funktion, die beim OnTerminate-Ereignis ausgeführt wird macht etwa folgendes:
Delphi-Quellcode:
StatusBar.Panels[0].Text := 'Identnummernliste steht bereit';
{ andere Dinge sind auskommentiert, Absturz erfolgt dennoch }
IdentListThread.Free;
IdentListThread := nil;

Da greifst du unsynchronisiert auf die VCL zu. Lagere das aus in eine extra Prozedur und rufe es synchronisiert auf:

Delphi-Quellcode:
procedure TThread.Blubb;
begin
  StatusBar.Panels[0].Text := 'Identnummernliste steht bereit';
end;

procedure TThread.Terminate;
begin
  Synchronize(Blubb);
end;
Also nur so grob die Art und Weise. Also so würde ich's machen. :gruebel:

m_junglas 1. Mär 2006 01:42

Re: Programmabsturz! Warum?
 
Hi!

Matze: ich greife nur aus dem OnTerminate-Ereignis auf die VCL zu und das ist laut Delphi v.a. der Sinn der Sache, denn der Code wird im VCL-Kontext aufgerufen und Zugriffe auf die VCL usw. sind von dort aus sicher.

ABER.. HA! .. nach 6 Tagen Nervenzusammenbruch habe ich den Fehler gefunden:

Im OnTerminate-Ereignis darf man NICHT den Thread freigeben!

Ich habe das "FreeOnTerminate" Property auf false gesetzt und bin davon ausgegangen, dass ich "aus dem VCL-Kontext" (lt. Hilfe) dann am Ende den Thread freigeben kann, nachdem ich die nötigen Daten herausgezogen habe.
Offensichtlich kam es NACH (!) meiner Prozedur dann in der SYSTEM-Unit zu einer EAccessViolation-Exception. Zumindest oft, aber nicht immer. Bei meinen vielen Tests kam die Exception mal früher, mal später und je nach PC garnicht.

Die Lösung ist also DOCH "FreeOnTerminate" zu setzen, denn das OnTerminate-Event tritt noch vor Destroy() auf und so ist so oder so der Zugriff auf den Thread noch möglich. Nach der Prozedur wird der Thread freigegeben und gelöscht.

Offensichtlich wird intern so einiges mit Messages macht. Ein "thread.free" heisst noch LANGE nicht, dass danach alles freigegben wurde. Die Fassade, die Delphi einem hier bietet ist hier also recht brüchig.

Die Onlinehilfe ist hier zu schwammig - allerdings arbeite ich ja "noch" mit Delphi 6.
Da steht, dass man um auf den Thread zugreifen zu können immer "FreeOnTerminate" auf false setzen muss, denn sonst könnte schon nach dem nächsten Befehl der Thread abgearbeitet und entfernt sein.
Das habe ich gemacht und da "OnTerminate" ja im VCL-Kontext ausgeführt werden sollte (lt. Hilfe) habe ich den Thread dann dort auch freigegeben.
Das war quasi ein Missverständnis.
Offenbar gehört selbst das OnTerminate()-Ereignis zum Thread und dann kracht es... je nach timing früher oder später.

Soweit meine Theorie.

Der ProcessExplorer von SysExternals hat mir hier gute Dienste erwiesen!

Tschüss

/\/\arcus (endlich wirklich happy!)


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz