我想知道我是否找到了编译器错误?我正在从我的应用程序中删除一些旧代码,现在我在“开始”处获得stackoverflow(请参阅下面的代码和反汇编)。
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;
任何想法?
谢谢你! 熔点答案 0 :(得分:2)
正在创建一个320 KB的缓冲区。你在这个调用链中有任何这些对象在其中有一个静态分配的巨大数组吗?也许它正在尝试将其中一个返回的对象放入堆栈中。
答案 1 :(得分:2)
以下代码似乎是问题所在:
m_SelectedRTMMenuData.ChannelMeasSet.MeasKV.ClearMeasurementData;
看起来ChannelMeasSet是一个巨大的数据结构,编译器因某种原因试图将其复制到您的堆栈中。我不确定为什么编译器会在没有看到对象声明的其余部分的情况下尝试这样做。此外,编译器似乎已在堆栈上分配了两个单独的临时存储区域,每个区域对应于您调用此区域(即使在任何给定时间只使用一个)。
您至少有两种可能的解决方案:
答案 2 :(得分:1)
Yuliy是对的:320KB缓冲区很可能是ChannelMeasSet返回的数组[20] - 基于rep movsd循环的大小。
看起来你有一些代码按值返回一个非常大的数据结构,而不仅仅是对它的引用。除了堆栈溢出问题,这可能是非常低效的。
答案 3 :(得分:0)
谢谢你的建议!这是调用堆栈(来自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
我正在处理你的更多评论。几分钟后回来。
不可否认,周围有一些中等大小的结构。我怀疑他们在那么近的地方,但我很快就会回复你。答案 4 :(得分:0)
m_SelectedRTMMenuData a small object
ChannelMeasSet a record
MeasKV a record with method ClearMeasurementData( );
奇怪的是,该应用程序刚刚被剥离了一堆旧代码。我从未见过像这样的堆栈溢出。
我会发布此评论,以便在我完成之前不会被销毁!
谢谢你的帮助!