![]() |
Exception - Register + DataStack
Hallo ne Frage, es gibt ja Tools, die können bei einer Exception die CPU Register + DatenStack mit ausgeben.
Sowas wäre ja prinzipiell nicht schlecht, zB.: Könnte man da bei sowas
Delphi-Quellcode:
vermutlich dann anhander der Register automatisch sehen auf was der Zähler i gerade steht (zumindest wenn man sich dann den Assembler Code ansieht dann ja ganz sicher)
for i:=0 to Count-1 do Item[i].Free;
wie kommt man auf diese Register? bzw wie nennt sich das System mit dem man sowas auslesen kann? Für mich ist es leider ja unlogisch, da ja die exception Routine das alles ja total verändert - daher verstehe ich das nicht wirklich ;) |
AW: Exception - Register + DataStack
Verstanden habe ich das auch nie ganz, aber wenn du das schon im Delphi-Debugger nicht mehr sehen kannst, wie soll das dann noch ein externes Tool sehen können? Die Info scheint dann echt zu sein.
|
AW: Exception - Register + DataStack
Meinst du sowas wie MadExcept, Eurekalog oder das, was in der Jedi JCL enthalten ist?
|
AW: Exception - Register + DataStack
ja genau madExcept zb kann eben die CPU Register anzeigen, und vorallem wenn mal ne exception in einer Schleife passiert wäre der CX oder was auch immer doch sehr interessant, oder eben generell der Daten-Stack.
Wenn man sich dann den Assemblercode ansieht dann kann man ja rausfinden wo die Schleifenvariable steht, und wüsste bei welchen Eintrag die Exception aufgetreten ist - wenn ich den Bug vom Kunden bekomme. |
AW: Exception - Register + DataStack
Erstmal müsste diese Variable dann auch in den Registern liegen, was sie hier bestimmt nicht tut, da dieses Register über den Free/Destroy-Aufruf (und wer weiß was sonst noch alles darin passiert) ungültig/überschrieben würde.
Proderuren/Funktionen sind nicht verpflichtet Register sicherzustellen. (abgesehn von ein/zwei bestimmten Registern, wie EBX, in welchem diese Variable aber bestimmt nicht liegen wird) In diesem Fall wird die Variable auf dem Stack liegen. Wie: ![]() |
AW: Exception - Register + DataStack
Zitat:
|
AW: Exception - Register + DataStack
Das was da vermutlich einen strich durch die Rechnung machen wird, ist das eventuell dort wo die exception dann passiert, die CPU Register schon wieder für was anderes verwendet wurden.
Aber wenn man CPU + Stack von dem Zeitpunkt hat wann die Exception aufgetreten ist, dann könnte man es theoretisch ja schön rekonstruieren. |
AW: Exception - Register + DataStack
Zitat:
Eine kurze schleife, ohne Funktionsaufrufe (CALL), da darfst du das gerne machen, also wenn dein Codestrück die ganze Zeit über die volle Kontrolle über die Register besitzt. Man kann sich bei sich selbst als Debugger registrieren. Da kann dann bei einer Exception ein anderer Thread diese Register auslesen, ohne beim Lesen (CodeAusführen) "diese" Register zu beeinflussen, genauso wie es der Debugger von Delphi macht. |
AW: Exception - Register + DataStack
Register auslesen ist relativ einfach (ich skizzier das mal für Windows).
Du ruftst ![]() Allerdings, wie schon zuvor erwähnt, sind das dann die Werte zu diesem Zeitpunkt - also wenn das derselbe Thread ist wie der gerade diesen Code ausführende, liegt die Wahrscheinlichkeit hoch dass das nicht mehr der Wert ist, der im Code vor der Exception da drin stand - um das rekonstruieren müsste man rückwärts den Code disassembeln und das macht meines Wissens nach keins der Tools wie madExcept. Beispiel: Ich hab den Code hier in nen ButtonClick geschrieben:
Delphi-Quellcode:
Der assembler code unter Win32 sieht so aus (mit
procedure ShowMsg(i: Integer);
begin ShowMessage(i.ToString); end; procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin for i := 1 to 10 do begin RaiseLastOSError; ShowMsg(i); end; end;
Delphi-Quellcode:
)
$O+W-
Code:
Wenn der call auf RaiseLastOSError passiert ist ebx also 1, aber im angezeigten madExcept bugreport Fenster steht dort bei mir im "cpu regs" Tab 00000000 drin, da bis dahin ebx wiederverwendet wurde
Unit1.pas.36: begin
0063A974 53 push ebx Unit1.pas.37: for i := 1 to 10 do 0063A975 BB01000000 mov ebx,$00000001 Unit1.pas.39: RaiseLastOSError; 0063A97A E8F9CDE1FF call RaiseLastOSError Unit1.pas.40: ShowMsg(i); 0063A97F 8BC3 mov eax,ebx 0063A981 E89EFFFFFF call ShowMsg Unit1.pas.41: end; 0063A986 43 inc ebx Unit1.pas.37: for i := 1 to 10 do 0063A987 83FB0B cmp ebx,$0b 0063A98A 75EE jnz $0063a97a Unit1.pas.42: end; 0063A98C 5B pop ebx 0063A98D C3 ret |
AW: Exception - Register + DataStack
Das stimmt so weit auch, denn nicht "RaiseLastOSError" löst die Exception aus, sondern das passiert ja eh erst später, weiter drinnen.
Delphi-Quellcode:
Mit DebugDCUs bis zum Raise, schauen was die CPU-Ansicht im Delphi sagt und das dann mit madExcept vergleichen.
procedure RaiseLastOSError;
begin RaiseLastOSError(GetLastError); end; procedure RaiseLastOSError(LastError: Integer); var Error: EOSError; begin if LastError <> 0 then Error := EOSError.CreateResFmt(@SOSError, [LastError, SysErrorMessage(LastError)]) else Error := EOSError.CreateRes(@SUnkOSError); Error.ErrorCode := LastError; raise Error; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:11 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