Only tested with 2.6.2 yet. Will see yf/when I get to test with trunk.
Also not reproduced on simple code yet, only in the IDE (on 2 different pieces of code, both involving for ...in)
Maybe it is already known?
It needs -O2( ( maybe higher / not tested), and it needs other checks disabled (and least some of them but y usual set of Criot gh gt did prevent it)
The finding is at the end. there is a
007EB390 50 push %eax
that does not get undone. (not in the flow the code follows in this case)
So that means next time esp is used, it is wrong.
Earlier message 154 lines
-------- Original Message --------
Subject: Re: [Lazarusdev] crash in View Forms Dialog - codetools
Date: Thu, 06 Feb 2014 00:26:34 +0000
From: Martin Frb
Reply-To: Lazarus Developers List
To: Lazarus Developers List
On 05/02/2014 23:43, Martin Frb wrote:
> On 05/02/2014 23:29, Mattias Gaertner wrote:
>>
>> Looking at the code I don't see how FTree can be nil.
>>
>> Can you check
>>
>> constructor TViewUnitsEntryEnumerator.Create(Tree: TAVLTree);
>> begin
>> FTree:=Tree;
>> end;
>>
>> if FTree is nil?
>>
>
> I am trying. With -O2 I must rely on sam and registers a lot.
>
> It appears to be there (Some value nil, that I still have to write
> down, and compare against the tree), and it is stored somewhere.
>
> I do have a feeling that it is a bug in fpc. But I have not yet
> tracked what exactly it is....
ok so step by step
procedure TViewUnitDialog.OKButtonClick(Sender: TObject);
viewunit_dlg.pp:465 for S2PItem in fEntries.fItems do begin
007EB35D 8b542428 mov 0x28(%esp),%edx
007EB361 8b82b0040000 mov 0x4b0(%edx),%eax
007EB367 8b4004 mov 0x4(%eax),%eax
007EB36A e8c1c5e5ff call 0x647930 <GETENUMERATOR>
007EB36F 8944242c mov %eax,0x2c(%esp)
The only argument is eax, so I guess that is TStringToPointerTree. If so
then this is it, and looks good)
TStringToPointerTree($eax)
at address 292259264
<TSTRINGTOPOINTERTREE> = { <TSTRINGMAP> = { <TOBJECT> = {
_vptr$TOBJECT = $f39514},
FCOMPAREKEYITEMFUNC = { function (POINTER, POINTER) :
LONGINT} 0x116b85c4,
FTREE = $116b85e0,
FCASESENSITIVE = false,
CASESENSITIVE = false,
TREE = $116b85e0,
COMPAREKEYITEMFUNC = { function (POINTER, POINTER) :
LONGINT} 0x116b85c4},
FFREEVALUES = false,
FREEVALUES = false}
------------------------------------------
function TStringToPointerTree.GetEnumerator: TStringToPointerTreeEnumerator;
generates only the following asm *from debugger view) , no stack frame
FTree at 0x8(%eax) seems right
codetoolsstructs.pas:734
Result:=TStringToPointerTreeEnumerator.Create(FTree);
00647930 8b4808 mov 0x8(%eax),%ecx
00647933 bac095f300 mov $0xf395c0,%edx
00647938 b800000000 mov $0x0,%eax
0064793D e80e000000 call 0x647950 <CREATE>
codetoolsstructs.pas:735 end;
calculating the address by hand, I get (count = 0 may be correct, since
the list was empty / crash happens with items in list too)
at addr 292259296 / 0x116b85e0
<TAVLTREE> = { <TOBJECT> = { _vptr$TOBJECT = $116b85e0},
FONCOMPARE = { function (POINTER, POINTER) : LONGINT}
0x116b85cc,
FCOUNT = 0,
FNODEMGRAUTOFREE = false,
FNODEMGR = $6f,
ROOT = $7a9c021,
ONCOMPARE = { function (POINTER, POINTER) : LONGINT} 0x116b85cc,
COUNT = 0}
ftree goes in ecx to create
in CREATE:
codetoolsstructs.pas:741 FTree:=Tree;
006479AF 897b04 mov %edi,0x4(%ebx)
Assuming that ebx is self in create, edi indeed still contains ftree
AFTER create the iterator looks (again, if I got the right address
TStringToPointerTreeEnumerator(0x1077b8b0)
<TSTRINGTOPOINTERTREEENUMERATOR> = { <TSTRINGMAPENUMERATOR> = {
<TOBJECT> = { _vptr$TOBJECT = $f395c0},
FTREE = $116b85e0, <<<<<<<<<<<<< same as above, ok
FCURRENT = $0},
}
back in buttonclick:
viewunit_dlg.pp:465 for S2PItem in fEntries.fItems do begin
007EB3D8 8b44242c mov 0x2c(%esp),%eax
007EB3DC e85fc6e5ff call 0x647a40 <MOVENEXT>
ARGGGHHH NOw I missed where the value changed, but now it is 0x116fa658
And that in the TViewUnitDialog: MoveNext is called with TViewUnitDialog
as self.
--------------
Ok found it
viewunit_dlg.pp:465 for S2PItem in fEntries.fItems do begin
007EB35D 8b542428 mov 0x28(%esp),%edx
007EB361 8b82b0040000 mov 0x4b0(%edx),%eax
007EB367 8b4004 mov 0x4(%eax),%eax
007EB36A e8c1c5e5ff call 0x647930 <GETENUMERATOR>
007EB36F 8944242c mov %eax,0x2c(%esp)
007EB373 85c0 test %eax,%eax
007EB375 0f848e000000 je 0x7eb409 <OKBUTTONCLICK+233>
007EB37B 89e1 mov %esp,%ecx
007EB37D 8d54240c lea 0xc(%esp),%edx
007EB381 b801000000 mov $0x1,%eax
007EB386 e8d522c2ff call 0x40d660 <fpc_pushexceptaddr>
007EB38B e86048c2ff call 0x40fbf0 <fpc_setjmp>
007EB390 50 push %eax
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< change esp
007EB391 85c0 test %eax,%eax
007EB393 7550 jne 0x7eb3e5 <OKBUTTONCLICK+197>
<<<<<<<<<<<<<<<<<<< this jump is followed
007EB395 eb41 jmp 0x7eb3d8 <OKBUTTONCLICK+184>
007EB397 90 nop
007EB398 8b44242c mov 0x2c(%esp),%eax
007EB39C e8dfc6e5ff call 0x647a80 <GETCURRENT>
007EB3A1 89c6 mov %eax,%esi
viewunit_dlg.pp:466 Entry:=TViewUnitsEntry(S2PItem^.Value);
And then we get to
viewunit_dlg.pp:465 for S2PItem in fEntries.fItems do begin
007EB3D8 8b44242c mov 0x2c(%esp),%eax
007EB3DC e85fc6e5ff call 0x647a40 <MOVENEXT>
007EB3E1 84c0 test %al,%al
only 0x2c(%esp) is wrong, because esp is wrong now.