Reputation: 2846
i wonder if i've found a compiler bug? i was removing some old code from my app and now i get stackoverflow at "begin" (see code & disassembly below).
procedure TfraNewRTMDisplay.ShowMeasurement;
var
iDummy, iDummy2, iDummy3:integer;
begin // STACK OVERFLOW BEFORE MY CODE STARTS
iDummy:=0;
iDummy2:=0;
case iDummy2 of
1:
case iDummy of
1:m_SelectedRTMMenuData.ChannelMeasSet.MeasKV.ClearMeasurementData;
2:m_SelectedRTMMenuData.ChannelMeasSet.MeasKV.ClearMeasurementData;
end;
end;
end;
NewRTMDisplay.pas.1601: begin
00983BF8 55 push ebp
00983BF9 8BEC mov ebp,esp
00983BFB B9D4E40400 mov ecx,$0004e4d4
00983C00 6A00 push $00 // stack overflow loop
00983C02 6A00 push $00 // stack overflow loop
00983C04 49 dec ecx // stack overflow loop
00983C05 75F9 jnz $00983c00 // stack overflow loop
00983C07 56 push esi
00983C08 57 push edi
00983C09 8945FC mov [ebp-$04],eax
00983C0C 8D856005FFFF lea eax,[ebp-$0000faa0]
00983C12 8B153C789A00 mov edx,[$009a783c]
00983C18 E88B35A8FF call @InitializeRecord
00983C1D 8D85D00AFEFF lea eax,[ebp-$0001f530]
00983C23 8B153C789A00 mov edx,[$009a783c]
00983C29 E87A35A8FF call @InitializeRecord
00983C2E 33C0 xor eax,eax
00983C30 55 push ebp
00983C31 68F73C9800 push $00983cf7
00983C36 64FF30 push dword ptr fs:[eax]
00983C39 648920 mov fs:[eax],esp
NewRTMDisplay.pas.1602: iDummy:=0;
00983C3C 33C0 xor eax,eax
00983C3E 8945F8 mov [ebp-$08],eax
NewRTMDisplay.pas.1603: iDummy2:=0;
00983C41 33C0 xor eax,eax
00983C43 8945F4 mov [ebp-$0c],eax
NewRTMDisplay.pas.1605: case iDummy2 of
00983C46 8B45F4 mov eax,[ebp-$0c]
00983C49 48 dec eax
00983C4A 7571 jnz $00983cbd
NewRTMDisplay.pas.1607: case iDummy of
00983C4C 8B45F8 mov eax,[ebp-$08]
00983C4F 48 dec eax
00983C50 7405 jz $00983c57
00983C52 48 dec eax
00983C53 7436 jz $00983c8b
00983C55 EB66 jmp $00983cbd
NewRTMDisplay.pas.1608: 1:m_SelectedRTMMenuData.ChannelMeasSet.MeasKV.ClearMeasurementData;
00983C57 8D951872EBFF lea edx,[ebp-$00148de8]
00983C5D 8B45FC mov eax,[ebp-$04]
00983C60 8B80F0020000 mov eax,[eax+$000002f0]
00983C66 E895DBE9FF call TRTMMenuData.ChannelMeasSet
00983C6B 8DB52072EBFF lea esi,[ebp-$00148de0]
00983C71 8DBD6005FFFF lea edi,[ebp-$0000faa0]
00983C77 B9A43E0000 mov ecx,$00003ea4
00983C7C F3A5 rep movsd
00983C7E 8D856005FFFF lea eax,[ebp-$0000faa0]
00983C84 E81B3F0200 call TDeviceMeas.ClearMeasurementData
00983C89 EB32 jmp $00983cbd
NewRTMDisplay.pas.1609: 2:m_SelectedRTMMenuData.ChannelMeasSet.MeasKV.ClearMeasurementData;
00983C8B 8D9560D9D8FF lea edx,[ebp-$002726a0]
00983C91 8B45FC mov eax,[ebp-$04]
00983C94 8B80F0020000 mov eax,[eax+$000002f0]
00983C9A E861DBE9FF call TRTMMenuData.ChannelMeasSet
00983C9F 8DB568D9D8FF lea esi,[ebp-$00272698]
00983CA5 8DBDD00AFEFF lea edi,[ebp-$0001f530]
00983CAB B9A43E0000 mov ecx,$00003ea4
00983CB0 F3A5 rep movsd
00983CB2 8D85D00AFEFF lea eax,[ebp-$0001f530]
00983CB8 E8E73E0200 call TDeviceMeas.ClearMeasurementData
NewRTMDisplay.pas.1612: end;
any ideas?
thank you! mp
Upvotes: 4
Views: 468
Reputation: 992747
The following code appears to be the problem:
m_SelectedRTMMenuData.ChannelMeasSet.MeasKV.ClearMeasurementData;
It looks like ChannelMeasSet is a huge data structure that the compiler is trying to copy to your stack for some reason. I'm not sure why the compiler would attempt to do that without seeing the rest of your object declaration. Furthermore, the compiler appears to have allocated two separate temporary storage areas on the stack, one for each line where you call this (even though only one will be used at any given time).
You have at least two possible solutions:
Upvotes: 2
Reputation: 2846
stupid site; it auto refreshed, wiping out my answer. ChannelMeasSet is a record that surprised me that it occupies 1.2 MB!
m_SelectedRTMMenuData a small object
ChannelMeasSet a record
MeasKV a record with method ClearMeasurementData( );
strangely, the app was just now having a bunch of old code being stripped out. i have never seen a stack overflow like this one.
i'll post this comment so it doesn't get destroyed before i can finish!
thank you for your help!
Upvotes: 0
Reputation: 2846
thank you for your suggestions! here is the call stack (from delphi 2009).
NewRTMDisplay.TfraNewRTMDisplay.ShowMeasurement
NewRTMDisplay.TfraNewRTMDisplay.DetectorSelectionChange($46552D0,drmOneAtATime)
NewRTMDisplay.TfraNewRTMDisplay.pumOnDetectorSelectionChange($46129E0)
Menus.TMenuItem.Click
Menus.TMenu.DispatchCommand(???)
Menus.TPopupList.WndProc((273, 386, 0, 0, 386, 0, 0, 0, 0, 0))
Menus.TPopupList.MainWndProc(???)
Classes.StdWndProc(15403740,273,386,0)
:7e418734 USER32.GetDC + 0x6d
:7e418816 ; C:\WINDOWS\system32\USER32.dll
:7e4189cd ; C:\WINDOWS\system32\USER32.dll
:7e418a10 USER32.DispatchMessageW + 0xf
Forms.TApplication.ProcessMessage(???)
:0051e31c TApplication.ProcessMessage + $F8
am working on more of your comments here right now. come back in a few minutes.
admittedly there are some moderately large structs around. i doubt they're anywhere near that big but i'll get back to you shortly.
Upvotes: 0
Reputation: 68023
Yuliy is right: The 320KB buffer is likely an array[20] of whatever is returned by ChannelMeasSet - based on the size of the rep movsd loop.
It looks like you've got some code that is returning a very large data structure by value, rather than just a reference to it. Apart from the stack overflow issue, that's likely to be very inefficient.
Upvotes: 1
Reputation: 17718
Something's creating a 320 KB buffer. Do you have any of those objects in that chain of calls have a statically allocated huge array inside them? Perhaps it's trying to fit one of the returned objects onto the stack.
Upvotes: 2