Autor |
Beitrag |
winx
      
Beiträge: 249
|
Verfasst: Fr 17.02.06 15:54
Hallo,
ich habe ein riesen Problem in meinem Programm. Und zwar kommen manchmal am Ende des programmes Zugrissverletzungen.
Wenn ich folgenden Vorgang durchführe:
- Programm starten
- Text eingeben
- Programm beenden.
erscheinen in unregelmäßigen Abständen Zugriffsverletzungen und das Tool hängt sich auf.
Auch wenn ich IMMER den selben Vorgang durchführe, erscheinen diese nicht immer.
Wenn ich dann debuge um den Fehler zu finden. findet er ne tolle Speicheradresse (CPU)...das hilft mir
auch nicht mehr weiter.
Habt ihr ne Idee, was genau ich machen kann, um den Fehler zu finden???
Das Programm ist relativ groß und komplex, deswegn lohnt es sich auch nicht Source Code zu posten.
Es verwendet sowohl DLLs als auch Komponenten.
Ach ja: Das Tool wurde von D7 auf D2006 portiert, unter D7 kamen KEINE Zugriffsverletzungen.
Ich weiss echt nich mehr was ich noch machen soll!!!
Danke für jeden Tip,
winx
|
|
Kroko
      
Beiträge: 1284
W98 W2k WXP
Turbo D
|
Verfasst: Fr 17.02.06 16:01
prüfe alle Index von dynamischen Array's, da liegt zu 90% der Fehler 
_________________ Die F1-Taste steht nicht unter Naturschutz und darf somit regelmäßig und oft benutzt werden! oder Wer lesen kann, ist klar im Vorteil!
|
|
winx 
      
Beiträge: 249
|
Verfasst: Fr 17.02.06 16:10
der Fehler tritt aber erst nach dem Ende auf:
sprich in der Project Datei:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| begin Application.Initialize;
Application.CreateForm(Tmainform, mainform); Application.Run;
end. |
Also bis zum Debugpunkt kein Fehler, dann ab und an ne Zugriffsverletzung
|
|
Kroko
      
Beiträge: 1284
W98 W2k WXP
Turbo D
|
Verfasst: Mo 20.02.06 13:46
ohne GLASKUGEL und Quellen wirds schwer!
(1) Überprüfe alle Array's -> Compilerschalter überlauf mal setzen
(2) eigene Komponenten -> ev. Freigabe doppelt oder Zugriff auf bereits freigegebene Comp.
_________________ Die F1-Taste steht nicht unter Naturschutz und darf somit regelmäßig und oft benutzt werden! oder Wer lesen kann, ist klar im Vorteil!
|
|
csa
      
Beiträge: 22
Win XP
Delphi 2005 Prof.
|
Verfasst: Di 21.02.06 21:20
Der Fehler tritt wahrscheinlich in einem Finalization-Abschnitt auf. Wenn nicht das nicht im eigenen Quellcode passiert, kann man testweise die RTL- und VCL-Quellen (statt der DCUs aus dem Delphi-Lib-Verzeichnis) einbinden, und mit Range-Check kompilieren.
Als Ursache würde ich ein freigegebenes Objekt vermuten, dessen Destructor beim Aufräumen erneut aufgerufen wird. Da der Destructor virtuell ist, springt der Programmablauf an einen undefinierten Punkt, falls der Speicherbereich der VMT bereits überschrieben wurde. Der Debugger kommt da nicht mehr mit.
Verdächtig sind VCL-Komponenten, die mit Free abgeräumt werden, da sich möglicherweise der Owner zu einem erneuten Free berufen fühlt, falls er das Ableben seiner Child-Komponente nicht mitbekommen hat.
COM und OLE können auch Fehlermeldungen beim Beenden des Programms bringen, falls man nicht alle Interface-Variablen gewissenhaft auf nil gesetzt hat.
|
|
winx 
      
Beiträge: 249
|
Verfasst: Do 23.02.06 09:56
Danke, werd das mal probieren
aber wie muß ich vorgehen um
a) " testweise die RTL- und VCL-Quellen (statt der DCUs aus dem Delphi-Lib-Verzeichnis) einbinden"
b) wie aktiviere ich den " Range-Check "
danke...
|
|
csa
      
Beiträge: 22
Win XP
Delphi 2005 Prof.
|
Verfasst: Do 23.02.06 12:57
RTL- und VCL-Quellen einbinden geht natürlich nur, wenn sie da sind (Delphi Prof. oder Enterprise). Dann liegen sie parallel zum Lib-Verzeichnis unter Source. In den Konfigurationsdateien sieht das dann statt so ...:
Quelltext 1:
| -U"c:\programme\anwendungen\d2005\lib" |
... so aus:
Quelltext 1:
| -U"c:\programme\anwendungen\d2005\source\Win32\vcl;c:\programme\anwendungen\d2005\source\Win32\rtl\common;c:\programme\anwendungen\d2005\source\Win32\rtl\Win;c:\programme\anwendungen\d2005\source\Win32\Internet;c:\programme\anwendungen\d2005\source\Win32\xml;c:\programme\anwendungen\d2005\source\Win32\db;c:\programme\anwendungen\d2005\source\Win32\Indy9;c:\programme\anwendungen\d2005\lib" |
Ein "-Ajpeg=classes" hilft dabei, die fehlende jpeg.pas zu ignorieren (die durfte Borland aus lizenzrechtlichen Gründen nicht beilegen).
Im Dialog "Projektoptionen" ist das auf der Seite "Verzeichnisse/Bedingungen" unter "Suchpfad" einstellbar. Dort kann der Pfad zu Delphi mit $(DELPHI) abgekürzt werden.
Range-Check ist das -$R+ in den Konfigurationsdateien, bzw. die Checkbox "Bereichsprüfung" auf der Seite "Compiler" des Dialogs "Projektoptionen".
Möglicherweise ist das bei D2006 alles etwas anders. Ich werde mir allerdings kein D2006 zulegen, bevor nicht erst einmal D2005 einigermaßen stabil läuft (also wahrscheinlich garnicht mehr).
_________________ Man sollte nie die gleiche Dummheit zweimal machen, denn die Auswahl ist groß genug. (Bertrand Russell)
|
|
winx 
      
Beiträge: 249
|
Verfasst: Do 23.02.06 14:33
"also wahrscheinlich garnicht mehr"
wieso denkst du das?
|
|
csa
      
Beiträge: 22
Win XP
Delphi 2005 Prof.
|
Verfasst: Do 23.02.06 14:54
> wieso denkst du das?
Weil ich mit der Stabilität von D2005 unzufrieden bin (Schutzverletzungen der IDE, ein TLB-Editor, der sich mit Umlauten selbst ein Bein stellt, sporadischer Verlust von Änderungen an Quelltexten, Inline noch nicht stabil, Performance der IDE), aber die Updates bereits nach einem halben Jahr eingestellt wurden. Der einzige Grund, warum ich nicht zurück zu D7 gegangen bin, ist das Inline. Jetzt warte ich erst einmal, wie lange D2006 mit Updates unterstützt wird - wenn wieder ein halbfertiges Produkt übrig bleibt, schaue ich mir lieber mal das Visual Studio an. Der Lernaufwand von Delphi nach C# dürfte nicht so groß sein, wie der von der Windows-API nach .NET - und den habe ich sowieso vor mir.
_________________ Man sollte nie die gleiche Dummheit zweimal machen, denn die Auswahl ist groß genug. (Bertrand Russell)
|
|
winx 
      
Beiträge: 249
|
Verfasst: Do 23.02.06 15:51
mich kotzts (sorry) um Moment auch ultra an, das ich (noch) keine chance habe, diesen unregelmäßig auftretenten Fehler zu finden, vielleicht ist es ja ein IDE bug?!?!?!?!?
wohl nicht, aber das fehler suchen nervt ultra
vor allem, weil man eben nich weiss, wo man anfangen soll...
hab jetzt schon alle finalization aukommentiert -> bringt auch nix,
verschd Komponenten neu installiert -> ändert auch nix
ich kann mich doch nie durch den System Code durchwühlen.
Ach noch eins: der Stack der Fehlermeldung die das Tool madexcept brint sieht folgendermaßen aus:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71:
| allocated memory : 23,97 MB executable : MAk.exe exec. date/time : 2006-02-23 13:33 madExcept version : 3.0b callstack crc : $9bc2b3c6, $7b1cbfab, $431ee1f6 exception number : 1 exception class : EAccessViolation exception message : Zugriffsverletzung bei Adresse 00401A67 in Modul 'MAk.exe'. Schreiben von Adresse 0061005C.
main thread ($3bc): 00401a67 +043 MAk.exe System 25 +0 SysGetMem 00402f14 +004 MAk.exe System 25 +0 @GetMem 00455480 +008 MAk.exe SysUtils StrAlloc 004554b1 +019 MAk.exe SysUtils StrNew 004b37e1 +021 MAk.exe Controls TWinControl.WMDestroy 004ae00b +2bb MAk.exe Controls TControl.WndProc 004b1e34 +46c MAk.exe Controls TWinControl.WndProc 005cdf06 +132 MAk.exe VirtualTrees 23061 +32 TBaseVirtualTree.WndProc 004b15ec +02c MAk.exe Controls TWinControl.MainWndProc 00473e14 +014 MAk.exe Classes StdWndProc 7c91eae0 +010 ntdll.dll KiUserCallbackDispatcher 77d1daf4 +00a USER32.dll DestroyWindow 004b1088 +028 MAk.exe Controls TWinControl.DestroyWindowHandle 004c424b +033 MAk.exe Forms TCustomForm.DestroyWindowHandle 004c1353 +073 MAk.exe Forms TCustomForm.Destroy 00473007 +047 MAk.exe Classes TComponent.DestroyComponents 004bf602 +032 MAk.exe Forms DoneApplication 00453d26 +026 MAk.exe SysUtils DoExitProc 00405941 +021 MAk.exe System 25 +0 @Halt0 00699742 +2fe MAk.exe MAk 143 +39 initialization
thread $1d4: 7c91eb94 +00 ntdll.dll KiFastSystemCallRet 7c91e397 +0a ntdll.dll NtReplyWaitReceivePortEx 0044e721 +0d MAk.exe madExcept CallThreadProcSafe 0044e78b +37 MAk.exe madExcept ThreadExceptFrame >> created by main thread ($3bc) at: 77e6760d +00 RPCRT4.dll
thread $444 (TWorkerThread): 7c91eb94 +00 ntdll.dll KiFastSystemCallRet 7c91e9be +0a ntdll.dll NtWaitForSingleObject 7c8025d5 +85 kernel32.dll WaitForSingleObjectEx 7c80253d +0d kernel32.dll WaitForSingleObject 005adeae +16 MAk.exe VirtualTrees 5151 +3 TWorkerThread.Execute 0044e83f +2b MAk.exe madExcept HookedTThreadExecute 00472790 +34 MAk.exe Classes ThreadProc 00405a3c +28 MAk.exe System 25 +0 ThreadWrapper 0044e721 +0d MAk.exe madExcept CallThreadProcSafe 0044e78b +37 MAk.exe madExcept ThreadExceptFrame >> created by main thread ($3bc) at: 005addd3 +23 MAk.exe VirtualTrees 5114 +1 TWorkerThread.Create
thread $578 (TIdUDPListenerThread): 7c91eb94 +00 ntdll.dll KiFastSystemCallRet 7c91e9be +0a ntdll.dll NtWaitForSingleObject 71a0150a +6a WS2HELP.dll WahReferenceContextByHandle 71a12e64 +a4 WS2_32.dll select 0044e83f +2b MAk.exe madExcept HookedTThreadExecute 0044e721 +0d MAk.exe madExcept CallThreadProcSafe 0044e78b +37 MAk.exe madExcept ThreadExceptFrame >> created by main thread ($3bc) at: 0225db87 +00 netmark.dll
thread $8e4: 7c91eb94 +00 ntdll.dll KiFastSystemCallRet 7c91e397 +0a ntdll.dll NtReplyWaitReceivePortEx 0044e721 +0d MAk.exe madExcept CallThreadProcSafe 0044e78b +37 MAk.exe madExcept ThreadExceptFrame >> created by thread $1d4 at: 77e6760d +00 RPCRT4.dll |
wo würdet ihr da zum suchen anfangen???
|
|
csa
      
Beiträge: 22
Win XP
Delphi 2005 Prof.
|
Verfasst: Do 23.02.06 16:23
also, dann ignorieren wir doch einfach mal alles, was wir nicht verstehen - übrig bleibt der Abschnitt "main thread". Den kann man von unten nach oben lesen, ganz oben die Schutzverletzung. Unten wird das Programm abgeräumt, in Zeile 27 sind wir im Finalization-Abschnitt von Forms.pas:
Delphi-Quelltext 1: 2:
| if Application <> nil then DoneApplication; |
mit:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure DoneApplication; begin with Application do begin ... DestroyComponents; end; end; |
Das DestroyComponents ruft Destroy für jedes Element aus der Liste Components auf. In Zeile 25 ist ein TCustomForm-Nachfolger dran. Der zerstört sein Handle, wobei eine WMDestroy-Message herumgesendet wird. Die landet bei TWinControl.WMDestroy:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TWinControl.WMDestroy(var Message: TWMDestroy); var Len: Integer; begin if FText = nil then begin Len := GetTextLen; if Len < 1 then FText := StrNew('') else begin FText := StrAlloc(Len + 1); GetTextBuf(FText, StrBufSize(FText)); end; end; inherited; RemoveWindowProps; end; |
- warum dort sichergestellt wird, dass FText Assigned ist, bleibt ein Geheimnis von Borland - wahrscheinlich ein Workaround von irgend etwas.
Ich vermute mal so ins Blaue hinein, der WinControl-Nachfolger wurde bereits zerstört, sodass bei FText := StrNew('') das Schreiben auf FText schief geht. Als erstes würde ich mir den mir unbekannten TBaseVirtualTree-Nachfolger genau anschauen (Zeile 18). Testhalber mal einen Brakepoint in dessen Destruktor setzen, um zu schauen, ob der wirklich erst am Ende, und auch wirklich nur einmal aufgerufen wird.
_________________ Man sollte nie die gleiche Dummheit zweimal machen, denn die Auswahl ist groß genug. (Bertrand Russell)
|
|
winx 
      
Beiträge: 249
|
Verfasst: Do 23.02.06 21:08
Hallo CSA,
erstmal tausend Dank für all deine Hilfe. Ich werdmir das ganz morgen mal genauer anschauen... noch ne mini-frage:
welche klasse verstehst du unter nachfolger ?
Bsp:
TForm
TForm1 = class(TForm)
Tform2 = class(TForm1)
wenn man das TForm1 betrachtet, sprichst du beim TForm vom Vorgänger und beim Tform2 vom Nachfolger, oder?
Nochmals danke,
winx
|
|
csa
      
Beiträge: 22
Win XP
Delphi 2005 Prof.
|
Verfasst: Do 23.02.06 22:44
Zitat: | wenn man das TForm1 betrachtet, sprichst du beim TForm vom Vorgänger und beim Tform2 vom Nachfolger, oder?
|
ja, die abgeleitete Klasse, in diesem Fall TVirtualTree oder so. Aber im Prinzip kann auch jede andere von TWinControl abgeleitete Klasse von einem doppelten Destroy betroffen sein, auch ein TForm beispielsweise.
Wenn alles nicht hilft, würde ich mal alle Quellen nach ".Free" und "FreeAndNil(" durchsuchen, und im Einzelfall schauen, ob alles mit rechten Dingen zugeht.
Viel Glück!
|
|
|