Har*_*vey 5 recursion stack mfc visual-c++
我有一个简单的递归函数RCompare(),它调用一个更复杂的函数Compare(),它在递归调用之前返回.每个递归级别使用248个字节的堆栈空间,这似乎比它应该的更多.这是递归函数:
void CMList::RCompare(MP n1) // RECURSIVE and Looping compare function
{
auto MP ne=n1->mf;
while(StkAvl() && Compare(n1=ne->mb))
RCompare(n1); // Recursive call !
}
Run Code Online (Sandbox Code Playgroud)
StkAvl()是一个简单的堆栈空间检查函数,它将自动变量的地址与存储在静态变量中的堆栈末尾附近的地址值进行比较.
在我看来,每次递归中唯一添加到堆栈的东西是两个指针变量(MP是指向结构的指针)和一个函数调用存储的东西,一些保存的寄存器,基本指针,返回地址等. ,所有32位(4字节)值.有没有办法是248字节呢?
我不知道如何在Visual Studio 2008中以有意义的方式实际查看堆栈.
谢谢
添加了反汇编:
CMList::RCompare:
0043E000 push ebp
0043E001 mov ebp,esp
0043E003 sub esp,0E4h
0043E009 push ebx
0043E00A push esi
0043E00B push edi
0043E00C push ecx
0043E00D lea edi,[ebp-0E4h]
0043E013 mov ecx,39h
0043E018 mov eax,0CCCCCCCCh
0043E01D rep stos dword ptr es:[edi]
0043E01F pop ecx
0043E020 mov dword ptr [ebp-8],edx
0043E023 mov dword ptr [ebp-14h],ecx
0043E026 mov eax,dword ptr [n1]
0043E029 mov ecx,dword ptr [eax+20h]
0043E02C mov dword ptr [ne],ecx
0043E02F mov ecx,dword ptr [this]
0043E032 call CMList::StkAvl (41D46Fh)
0043E037 test eax,eax
0043E039 je CMList::RCompare+63h (43E063h)
0043E03B mov eax,dword ptr [ne]
0043E03E mov ecx,dword ptr [eax+1Ch]
0043E041 mov dword ptr [n1],ecx
0043E044 mov edx,dword ptr [n1]
0043E047 mov ecx,dword ptr [this]
0043E04A call CMList::Compare (41DA05h)
0043E04F movzx edx,al
0043E052 test edx,edx
0043E054 je CMList::RCompare+63h (43E063h)
0043E056 mov edx,dword ptr [n1]
0043E059 mov ecx,dword ptr [this]
0043E05C call CMList::RCompare (41EC9Dh)
0043E061 jmp CMList::RCompare+2Fh (43E02Fh)
0043E063 pop edi
0043E064 pop esi
0043E065 pop ebx
0043E066 add esp,0E4h
0043E06C cmp ebp,esp
0043E06E call @ILT+5295(__RTC_CheckEsp) (41E4B4h)
0043E073 mov esp,ebp
0043E075 pop ebp
0043E076 ret
Run Code Online (Sandbox Code Playgroud)
为何选择0E4h?
更多信息:
class mch // match node structure
{
public:
T_FSZ c1,c2; // file indexes
T_MSZ sz; // match size
enum ntyp typ; // type of node
mch *mb,*mf; // pointers to next and previous match nodes
};
typedef mch * MP; // for use in casting (MP) x
Run Code Online (Sandbox Code Playgroud)
应该是一个普通的旧指针吗?结构本身中的指针相同,它们只是普通的4字节指针.
编辑:添加:
#pragma check_stack(off)
void CMList::RCompare(MP n1) // RECURSIVE and Looping compare function
{
auto MP ne=n1->mf;
while(StkAvl() && Compare(n1=ne->mb))
RCompare(n1); // Recursive call !
} // end RCompare()
#pragma check_stack()
Run Code Online (Sandbox Code Playgroud)
但它没有改变任何东西.:(
怎么办?
请注意,在调试模式下,编译器会在每个函数上绑定堆栈中的许多字节,
\n以捕获缓冲区溢出错误。
0043E003 sub esp, 0E4h ; < -- bound 228 bytes\n...\n0043E00D lea edi,[ebp-0E4h] \n0043E013 mov ecx, 39h \n0043E018 mov eax, 0CCCCCCCCh ; <-- sentinel\n0043E01D rep stos dword ptr es:[edi] ; <-- write sentinels\nRun Code Online (Sandbox Code Playgroud)\n\n编辑: OP Harvey 找到了打开/关闭堆栈探测器的编译指示。
\n\n\n\n\n\n\n如果指定了 off(或 \xe2\x80\x93),则指示编译器关闭堆栈探测;
\n
如果指定了 on(或 +),则指示编译器打开堆栈探测。
#pragma check_stack([ {on | off}] )\n#pragma check_stack{+ | \xe2\x80\x93}\nRun Code Online (Sandbox Code Playgroud)\n\n更新:嗯,看起来,探测器是另一个故事。
\n试试这个:/GZ(启用堆栈帧运行时错误检查)
| 归档时间: |
|
| 查看次数: |
1080 次 |
| 最近记录: |