Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 21:01

Foren-Übersicht » English » English Programming Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: access violation how to debug?
BeitragVerfasst: Fr Dez 26, 2008 10:57 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
I am getting an access violation (some number) in an application i am developeing with delphi2005pro.
The problem the access violation is raised after freeandnill(someobjec) is called.

This is the situation. In an onclick event for an button an object is created, used an finaly freeandnil is called. Only after the freeandnill is called the access violation is thrown.
Also i tried stepping through the code all the way butt all went well and after the freeandnill call the exception is there again. Now how do i debug that?

I do suspect something is going wrong in the object. But i am unable to debug it for now.

Any pointers to where i should look debug it in another way?

The offending class/object is the vfs i am developing.

Thanks for your help in advance.

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 11:05 
Offline
DGL Member

Registriert: Do Mai 30, 2002 18:48
Beiträge: 1617
turn of any optimizing first and then rebuild the whole. check again, where the access violation occurs and, if it is still in the nowhere after the free and nil call, check the CPU Debug Window (if that still exists in delphi 2005) to get a hint what happens right before the raise of the exception.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 11:30 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
Optimizations are off. And the error is still at the end; of the onclick code for the button.

So the cpu debug view. How do i read that? Or for that matter how do i copy its contents?

Also in the block where the error occurs looks like this:
Code:
  1.  
  2. TObject.InheritsFrom
  3. 004033B0 EB02             jmp $004033b4
  4. 004033B2 8B00             mov eax,[eax]
  5. 004033B4 39D0             cmp eax,edx
  6. 004033B6 7408             jz $004033c0
  7. 004033B8 8B40DC           mov eax,[eax-$24]        <-- this is the line where the code stops
  8.  

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 12:15 
Offline
DGL Member

Registriert: Do Mai 30, 2002 18:48
Beiträge: 1617
I don't know how to copy that.

Now what you see there is where within your code you broke down and - interestingly you are in the function TObject.InheritsFrom, checking if an object is an ancestor of a type. What you may be interested in is, if the register eax contains an adress that is very near to the object you just freed and nilled or belongs to the adress of the object that made the call, which could mean that freeing the object also freed the object that made the call (maybe through some recursion in the destructor), which of course is no good idea. Actually, eax at $004033B8 (thats the position within the machine code of your program) contains an adress, which is accessed through the use of the brackets [] in the mov statement. (That's why I think eax is interesting). Anyhow, if eax is 0, that idea doesn't help. (tip for reading assembler: mov is a bad name. actually mov is a put statement; so in your line eax is to be replaced with the value that is to be found at adress eax-$24.)

If that doesn't give you a hint, you can use the stack window (debug stack, stack trace, or whatever it is called in delphi) and try to figure out on which route the call to TObject.InheritsFrom came from your part of the application; in the hope that things do not end in question marks but in function names that would help you (you may be in a mess, if the function where the debugger placed the exception is not in that list); also, while tracing back the stack, you should be able to investigate the variables of the functions on that way (the adress of self may always be interesting, especially in comparsion to the object you just freed).

Things get especially interesting if the stack trace leads you into a lot of questionmarks instead of function names. then the names of the calling functions could not be determined, which may be caused by operating system calls or librarys you used. Then you should check if the object you freed or any child objects was not in use by an asynchronous library - or one of your threads. Checking the threads window before the free, after the free and after the crash may be interesting. No threads should die unexpectedly.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 12:47 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
Now the stacktrace provided some more usefull info:
:7c812aeb kernel32.RaiseException + 0x52
:00403598 NotifyNonDelphiException + $1C
:7c90327a ntdll.RtlConvertUlongToLargeInteger + 0x3c
:7c90e46a ntdll.KiUserExceptionDispatcher + 0xe
TVirtualFileSystem.WriteBlock(9,10,0,$9F818C)
TVirtualFileSystem.WriteVirtualFileStreamBuffer((no value),0,22472,(6, 7))
TVirtualFileStream.Write((no value),22472)
:004159d4 TStream.WriteBuffer + $18
TForm1.bDynWriteClick($9F616C)

Now i have to find the offending value?

But what i dont get how can the code reach the free part and beyond in the bDynWriteClick as it is even able to update a label there before showing the access violation error.

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 13:22 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
Somehow the code now seems to stop at the offending part. Maybe due to restarting delphi2005pro? I always thought a rebuild all did a complete rebuild. Not that it make more sense now.

Code:
  1.  
  2. procedure TVirtualFileSystem.WriteBlock(ablockid, anextblockid, aprevblockid: int64; pBuf: Pointer);
  3. begin
  4.   FDataFile.Position := (ablockid * FBlockSize); //goto begin of block
  5.   FDataFile.WriteBuffer(aprevblockid,sizeof(aprevblockid));
  6.   FDataFile.WriteBuffer(anextblockid,sizeof(anextblockid));
  7.   FDataFile.WriteBuffer(pbuf^,FBlockSize-(sizeof(int64)*2) );
  8. end;
  9.  


Somehow FDataFile becomes inaccesible? I dont believe that can happen with FDataFile when writing blocks in a row. So for now i go look what happens with FDataFile between the writeblock calls.

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 13:23 
Offline
DGL Member

Registriert: Do Mai 30, 2002 18:48
Beiträge: 1617
Updating the label may be done through the system UI thread and may not invoke an message/event (repaint/redraw) in your application; although, if the the new text of the label is set after the exception occurred, that would be very concerning.

Actually I think you can already read offending values in the stack trace. As far as I remember (I'm not completely sure on that), the first argument of functions within objects/classes in delphi is the self variable, so nil, "no value"(?!) or any low value could already give you an idea what is wrong. I don't know if you already noticed, but you should be able to double click into the stack trace to jump to the last call in that function, that invoked the call to the function further on top of the trace. There you can read the contents of variables, if that helps you. The Point where you lost control to the OS is the KiUserExceptionDispatcher function, which already belongs to the Exception Handling Process of the OS, so the offending call creating the access violation is in TVirtualFileSystem.WriteBlock(9,10,0,$9F818C).


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 13:27 
Offline
DGL Member

Registriert: Do Mai 30, 2002 18:48
Beiträge: 1617
noeska hat geschrieben:
Somehow FDataFile becomes inaccesible? I dont believe that can happen with FDataFile when writing blocks in a row. So for now i go look what happens with FDataFile between the writeblock calls.

Then you should pin it into your watches window... Maybe you overwrite it with some nonsense while over-filling some buffer? Calls to "Move()" are prone to that.

Also notice that we started this journey in "TObject.InheritsFrom". So I think restarting Delphi was a good Idea. If things still tend to be very obscure, a restart of your machine may help.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 14:27 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
Whow i found the offending part:

procedure TVirtualFileSystem.GetBlockId(var existingblock: Boolean; iEndBlock: Integer; var blocklistsize: Integer; var BlockList: TBlockList; i: Integer; var b: Int64; var nb: Int64);

You see GetBlockId was created using refactoring in delphi and i forgot to add a var declaration to blocklistsize.

Code:
  1.  
  2.     if BlockList = nil then
  3.     begin
  4.       BlockListSize := 0;
  5.       BlockListSize := BlockListSize + 1;
  6.       SetLength(BlockList, BlockListSize);
  7.     end
  8.     else
  9.     begin
  10.       BlockListSize := BlockListSize + 1;
  11.       SetLength(BlockList, BlockListSize);
  12.     end;
  13.     BlockList[i] := b;


So after 3 runs i goes out of sync with blocklistsize and then blocklist[i] := b manages to destroy the object based on TVirtualFileSystem of wich FDataFile is also an part. I still dont understand why but i do know i did not give GetBlockId the attention it deserverd. I better go clean it up and give better names to the vars used.

@Delphic: Thanks for helping me debugging my code and learn how to use the delphi ide debug tools better. I never used the stacktrace before. Thanks.

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 14:55 
Offline
DGL Member

Registriert: Do Mai 30, 2002 18:48
Beiträge: 1617
noeska hat geschrieben:
So after 3 runs i goes out of sync with blocklistsize and then blocklist[i] := b manages to destroy the object based on TVirtualFileSystem of wich FDataFile is also an part. I still dont understand why but i do know i did not give GetBlockId the attention it deserverd. I better go clean it up and give better names to the vars used.

So you wrote over array bounds? You can avoid this sort of problems by ticking "bound checking" (?) in the compiler options. See Debuggint Tutorial#Voreinstellungen . You will catch an IndexOutOfBounds Exception (or something like that) on trying to write - i.e. before you use the corrupted data ;-)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Dez 26, 2008 15:09 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
:oops: whoops i had that on for the executeable but not for the package where my vfs sourcecode is. I always turn on these runtime settings. I wonder why they were not on for the package. Now they are on :-) That out of bounds exception was something i expected to happen, but it did not. Now i know why.

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Apr 19, 2009 10:46 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1945
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
just saw this old thread ;)
There's one more thing to add: You can turn on "Debug DCUs" in the Delphi options. This allows you to inspect the source code of the Run Time Library during execution.
That way you should not require the CPU view at all, as almost the complete program code can be debugged within the Delphi IDE itself at the source code level.
Of course, using the CPU view does not harm at all ;) But it's somewhat harder to figure out than using the source.

Hope this helps,
~ Philipp

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Foren-Übersicht » English » English Programming Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 15 Queries | GZIP : On ]