Autor Beitrag
winx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 249



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1284

W98 W2k WXP
Turbo D
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 249



BeitragVerfasst: Fr 17.02.06 16:10 
der Fehler tritt aber erst nach dem Ende auf:

sprich in der Project Datei:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
begin
  
  Application.Initialize;

  Application.CreateForm(Tmainform, mainform);
  //...
  Application.Run; 

end//Hier steht der Haltepunkt


Also bis zum Debugpunkt kein Fehler, dann ab und an ne Zugriffsverletzung
Kroko
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1284

W98 W2k WXP
Turbo D
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22

Win XP
Delphi 2005 Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 249



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22

Win XP
Delphi 2005 Prof.
BeitragVerfasst: 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 ...:
ausblenden Quelltext
1:
-U"c:\programme\anwendungen\d2005\lib"					

... so aus:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 249



BeitragVerfasst: Do 23.02.06 14:33 
"also wahrscheinlich garnicht mehr"

wieso denkst du das?
csa
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22

Win XP
Delphi 2005 Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 249



BeitragVerfasst: 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:


ausblenden volle Höhe Quelltext
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22

Win XP
Delphi 2005 Prof.
BeitragVerfasst: 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:
ausblenden Delphi-Quelltext
1:
2:
  if Application <> nil then
    DoneApplication;

mit:
ausblenden 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:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 249



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22

Win XP
Delphi 2005 Prof.
BeitragVerfasst: 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!