AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein try..finally verursacht korrupte Variablen

try..finally verursacht korrupte Variablen

Ein Thema von prognase · begonnen am 17. Jul 2019 · letzter Beitrag vom 18. Jul 2019
Antwort Antwort
prognase

Registriert seit: 30. Apr 2012
4 Beiträge
 
#1

try..finally verursacht korrupte Variablen

  Alt 17. Jul 2019, 11:10
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:
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;
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.

Der ASM-Code dazu:

Code:
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
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.

Hat irgendwer eine Idee, was da nicht stimmen könnte? Jede Idee willkommen

Matthias
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.433 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#2

AW: try..finally verursacht korrupte Variablen

  Alt 17. Jul 2019, 11:19
Zitat:
Delphi-Quellcode:
  if closeLog then
     closeLog := not CloseLog;
ist total überflüssig
     closeLog = False; bewirkt das Selbe
Markus Kinzler

Geändert von mkinzler (17. Jul 2019 um 11:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: München
11.486 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: try..finally verursacht korrupte Variablen

  Alt 17. Jul 2019, 11:23
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.

......
Daniel W.
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
prognase

Registriert seit: 30. Apr 2012
4 Beiträge
 
#4

AW: try..finally verursacht korrupte Variablen

  Alt 17. Jul 2019, 19:14
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
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.508 Beiträge
 
#5

AW: try..finally verursacht korrupte Variablen

  Alt 17. Jul 2019, 21:17
Dann mal anders gefragt: Schaffst du es, dass die korrupten Infos irgendwo außerhalb vom Debugger sichtbar werden?
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.054 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

AW: try..finally verursacht korrupte Variablen

  Alt 18. Jul 2019, 10:09
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.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
prognase

Registriert seit: 30. Apr 2012
4 Beiträge
 
#7

AW: try..finally verursacht korrupte Variablen

  Alt 18. Jul 2019, 13:52
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:
  1. Debug_FINALLY_01: Breakpoint bei Einstieg in den FINALLY-Block, die Variablen haben die richtigen Werte
  2. Debug_FINALLY_02: Sobald der erste Befehl ausgeführt wurde, stimmen die Variablen nicht mehr bzw. sind "inaccessible"
  3. Debug_FINALLY_03: Für closeLog wird FALSE angezeigt, somit sollte der ELSE-Zweig aufgerufen werden
  4. Debug_FINALLY_04: ... das passiert aber nicht, somit scheint closeLog den erwarteten Wert TRUE zu haben
  5. Debug_FINALLY_05: Und am Ende der Methode werden alle Werte plötzlich wieder korrekt dargestellt, auch FScanActiveCounter wurde korrekt von 2 auf 1 runtergezählt

Ich denke also mal, der Debugger spinnt an dieser Stelle einfach, hat da schon mal jemand was ähnliches erlebt?

Matthias
Miniaturansicht angehängter Grafiken
debug_finally_01.jpg   debug_finally_02.jpg   debug_finally_03.jpg   debug_finally_04.jpg   debug_finally_05.jpg  

  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
7.211 Beiträge
 
Delphi XE4 Professional
 
#8

AW: try..finally verursacht korrupte Variablen

  Alt 18. Jul 2019, 14:05
Hallo,
Zitat:
hat da schon mal jemand was ähnliches erlebt
Ja, habe ich.
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.
Heiko
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf