delphi - Wrong code when combining anonymous and nested procedures -


i've got unexpected access violations delphi code think correct, seems miscompiled. can reduce to

procedure run(proc: tproc); begin   proc; end;  procedure test; begin   run(     procedure     var       s: pchar;        procedure nested;       begin         run(           procedure           begin           end);         s := 'hello, world!';       end;      begin       run(         procedure         begin           s := 'hello';         end);       nested;       showmessage(s);     end); end; 

what happens me s := 'hello, world!' storing in wrong location. because of that, either access violation raised, or showmessage(s) shows "hello" (and sometimes, access violation raised when freeing objects used implement anonymous procedures).

i'm using delphi xe, updates installed.

how can know going cause problems? know how rewrite code avoid anonymous procedures, have trouble figuring out in precisely situations lead wrong code, don't know avoid them.

it interesting me know if fixed in later versions of delphi, nothing more interesting, upgrading not option @ point.

on qc, recent report can find similar #91876, resolved in delphi xe.

update:

based on alexsc's comments, slight modification:

...        procedure nested;       begin         run(           procedure           begin             s := s;           end);         s := 'hello, world!';       end;  ... 

does work.

the generated machine code for

s := 'hello, world!'; 

in failing program is

scratchform.pas.44: s := 'hello, world!'; 004bd971 b89cd94b00       mov eax,$004bd99c 004bd976 894524           mov [ebp+$24],eax 

whereas correct version is

scratchform.pas.45: s := 'hello, world!'; 004bd981 b8b0d94b00       mov eax,$004bd9b0 004bd986 8b5508           mov edx,[ebp+$08] 004bd989 8b52fc           mov edx,[edx-$04] 004bd98c 89420c           mov [edx+$0c],eax 

the generated code in failing program not seeing s has been moved compiler-generated class, [ebp+$24] how outer local variables of nested methods accessed how local variables accessed.

without seeing whole assembler code whole (procedure test) , assuming on snippet posted, it's on failing snippet pointer has been moved on correct version there data moved too.

so seems s:=s or s:='' causes compiler create reference it's own , allocate memory, explain why works then.

i assume that's why access violation occurs without s:=s or s:='', because if there no memory allocated string (remember declared s: pchar) access violation raised because non-allocated memory accessed.

if declare s: string instead, won't happen.

additions after extended commenting:

a pchar pointer data structure, must exist. common issue pchar declare local variables , passing pchar variable other procs, because happens local variable freed once routine ends, pchar still point it, raise access violations once accessed.

the possibility exists per documentation declaring const s: pchar = 'hello, world!' works because compiler can resolve relative adresse it. works constants , not variables on example above. doing in example above needs storage allocated string literal pchar points s:string; p:pchar; s:='hello, world!'; p:=pchar(s); or similar.

if still fails declaring string or integer perhaps variable disappears somewhere along or isn't visible anymore in proc, issue has nothing existing pchar issue explained already.

final conclusion:

it's possible s:pchar; s:='hello, world!' compiler allocates local or global constant const s: pchar = 'hello, world!' saved executable, second s := 'hello' creates 1 saved executable , on - s points last 1 allocated, others still in executable not accessible more without knowing exact location, because s points last 1 allocated.

so depending 1 last s points either hello, world! or hello. on example above can guess 1 last , knows perhaps compiler can guess , depending on optimizations , other unpredictable factors s point unallocated mem instead of last 1 time showmessage(s) executed raises access violation.


Comments

Popular posts from this blog

html - How to style widget with post count different than without post count -

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

javascript - storing input from prompt in array and displaying the array -