![]() |
try..finally verursacht korrupte Variablen
Hi,
ich stehe etwas auf dem Schlauch, leider sind meine Assembler-Kenntnisse gefühlt auf 80er Jahre 8bit-Zeiten. Somit ist das Debugging meines fehlerhaften Codes schwierig. Ich habe eine Methode, in der ich einen TRY..FINALLY-Block nutze, dort setze ich Flags zur späteren Analyse. Beim Debugging fiel mir auf, dass >nach< dem ersten Befehl im FINALLY, wenn der durch exit oder abort ausgelöst wird, meine lokalen Variablen initialisiert bzw falsch sind, plus SELF plötzlich ein "inaccessible value" ist. Den Block habe ich immer mehr reduziert, bis nur noch dieses Fragment übrig geblieben ist:
Delphi-Quellcode:
Ich setze einen Breakpoint auf "Screen.Cursor ...", an dieser Stelle ist closeLog wahr, SELF hat einen Wert. Nach diesem Befehl ist closeLog falsch, i.e. $00, und auf SELF kann nicht zugegriffen werden.
procedure TFORM_LFH.BadBadTry;
var closeLog: Boolean; begin closeLog := False; try closeLog := True; exit; finally Screen.Cursor := crDefault; //-- some nonsense further code... if closeLog then closeLog := not CloseLog; end; end; Der ASM-Code dazu:
Code:
Wenn ich den Code in einem neuen Projekt nur mit einem Button als Auslöser nutze, habe ich das Problem nicht. Da sieht der ASM-Code auch anders aus.
LFH_Main.pas.1900: BadBadTry;
0000000001467E5B 488B8D80000000 mov rcx,[rbp+$00000080] 0000000001467E62 E8A9C2FFFF call TFORM_LFH.BadBadTry ... LFH_Main.pas.1135: begin 0000000001464110 55 push rbp 0000000001464111 4883EC40 sub rsp,$40 0000000001464115 488BEC mov rbp,rsp 0000000001464118 48896D28 mov [rbp+$28],rbp 000000000146411C 48894D50 mov [rbp+$50],rcx LFH_Main.pas.1136: closeLog := False; 0000000001464120 C6453F00 mov byte ptr [rbp+$3f],$00 LFH_Main.pas.1137: try 0000000001464124 90 nop LFH_Main.pas.1139: closeLog := True; 0000000001464125 C6453F01 mov byte ptr [rbp+$3f],$01 LFH_Main.pas.1140: exit; 0000000001464129 EB24 jmp TFORM_LFH.BadBadTry + $3F <- zu FINALLY LFH_Main.pas.1142: Screen.Cursor := crDefault; 000000000146412B 90 nop 000000000146412C 488B0525AD1600 mov rax,[rel $0016ad25] 0000000001464133 488B08 mov rcx,[rax] 0000000001464136 33D2 xor edx,edx 0000000001464138 E8D3733FFF call TScreen.SetCursor LFH_Main.pas.1144: if closeLog then 000000000146413D 807D3F00 cmp byte ptr [rbp+$3f],$00 0000000001464141 7417 jz TFORM_LFH.BadBadTry + $4A LFH_Main.pas.1145: closeLog := not CloseLog; 0000000001464143 807D3F00 cmp byte ptr [rbp+$3f],$00 0000000001464147 0F94C0 setz al 000000000146414A 88453F mov [rbp+$3f],al 000000000146414D EB0B jmp TFORM_LFH.BadBadTry + $4A 000000000146414F 33C9 xor ecx,ecx <- Ziel FINALLY 0000000001464151 488B5528 mov rdx,[rbp+$28] 0000000001464155 E806000000 call TFORM_LFH.BadBadTry + $50 <- zu $50 LFH_Main.pas.1147: end; 000000000146415A 488D6540 lea rsp,[rbp+$40] 000000000146415E 5D pop rbp 000000000146415F C3 ret LFH_Main.pas.1142: Screen.Cursor := crDefault; <- Ziel $50 0000000001464160 55 push rbp 0000000001464161 53 push rbx 0000000001464162 4883EC28 sub rsp,$28 <- danach §$% 0000000001464166 488BEC mov rbp,rsp 0000000001464169 4889D3 mov rbx,rdx 000000000146416C 488B05E5AC1600 mov rax,[rel $0016ace5] 0000000001464173 488B08 mov rcx,[rax] 0000000001464176 33D2 xor edx,edx 0000000001464178 E893733FFF call TScreen.SetCursor LFH_Main.pas.1144: if closeLog then 000000000146417D 807B3F00 cmp byte ptr [rbx+$3f],$00 0000000001464181 740A jz TFORM_LFH.BadBadTry + $7D Hat irgendwer eine Idee, was da nicht stimmen könnte? Jede Idee willkommen ;-) Matthias |
AW: try..finally verursacht korrupte Variablen
Zitat:
Delphi-Quellcode:
bewirkt das Selbe
closeLog = False;
|
AW: try..finally verursacht korrupte Variablen
Schalte mal die Compiler-Optimierungen aus. Die greifen hier ;-)
Grund, nach dem Screen.Cursor passiert nichts "wertvolles" mehr, du setzt eine lokale Variabel, die nie mehr gebraucht wird, also ist das einfach weggefallen durch den Compiler. Daher kannst Du auch auf deren Werte (wie auch auf Self) nicht mehr zugreifen. Die Methode wird beendet. ...:cat:... |
AW: try..finally verursacht korrupte Variablen
Dass der letzte Code-Block keinen Sinn macht ist klar, ist nur reingekommen, damit ich einen Breakpoint und "nächsten Schritt" habe. Im Original kommen da noch ca. zehn sinnvolle Anweisungen. Auch zeigt der ASM-Block, dass der nicht wegoptimiert wurde: ich laufe im DEBUG unter Winx64, alle Optimierungen ausgeschaltet. Der Fehler passiert im ASM-Code genau vor dem Setzen des Cursors, also noch im sinnvollen Code.
Ich glaube aber, dass ich den Fehler gefunden habe. Ich hab vergessen zu erwähnen auf was ich laufe: Delphi Rio, Ziel ist Win x64. Bin irgendwann mal darauf gekommen, dass mein Mini-Test-VCL in 32bit korrekt lief. Als ich das dann x64 übersetzt habe, gab es wieder das Problem. Ich werde das morgen noch mal weiter verfolgen und schreib dann was. Matthias |
AW: try..finally verursacht korrupte Variablen
Dann mal anders gefragt: Schaffst du es, dass die korrupten Infos irgendwo außerhalb vom Debugger sichtbar werden?
|
AW: try..finally verursacht korrupte Variablen
Mir ist aufgefallen, dass in 64-Bit viele Warnungen bzgl. uninitialisierten Variablen und möglicherweise undefinierten Funktionsergebnissen zu wirklichen Problemen werden (wer hätte das gedacht!). In 32-Bit hat man oft Glück und diese Warnungen verursachen zur Laufzeit keine Fehler. Hat mich auch verwundert als ich dann Code gefunden hab der eigentlich noch nie funktioniert haben konnte weil Variablen nicht initialisiert waren oder Funktionen unter Umständen kein Result gesetzt haben. In 64-Bit hats dann aber (wie erwartet) geknallt.
Ich würde also auch mal die Compiler Warnungen des Projekts durchlesen und bestenfalls alle beheben. Die Tatsache dass es in einem frischen Testprojekt klappt spricht dafür, dass du dir wahrscheinlich irgendwo was zerschossen hast. |
AW: try..finally verursacht korrupte Variablen
Liste der Anhänge anzeigen (Anzahl: 5)
Warnungen kommen von meiner Seite beim Kompilieren keine im Projekt, da achte ich drauf. Bei 3rd-Party mit Source kommen ein paar Warnungen, aber keine kritischen: Variable deklariert und nicht genutzt, zugewiesener Wert wird nicht genutzt usw.
Der Tipp mit "ausserhalb vom Debugger sichtbar machen" war noch mal gut: habe es >nicht< geschafft, die falschen Werte in einer MessageBox zu zeigen... stimmte immer. Also noch mal im Debugger länger und genauer geschaut heute Mittag. Ich vermute mal, dass der Debugger die Werte "nur" falsch anzeigt, irgendwie seine Zeiger in den Speicher verliert, aber: kurz vor Rücksprung stimmt scheinbar alles wieder. Angehängt ein paar Screenshots zum Nachverfolgen:
Ich denke also mal, der Debugger spinnt an dieser Stelle einfach, hat da schon mal jemand was ähnliches erlebt? Matthias |
AW: try..finally verursacht korrupte Variablen
Hallo,
Zitat:
Gerade wenn man eine Funktion als Watchpoint hat mit "Ausführen". Sehr lustig, wenn beim Debuggen sogar Code ausgeführt wird ... StringList.SaveToFile z.B. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:21 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-2025 by Thomas Breitkreuz