visual-c++ - 为什么每次递归都使用这么多的堆栈空间?

标签 visual-c++ mfc stack recursion

我有一个简单的递归函数 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 !
}

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              

为什么是 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

应该是一个普通的旧指针吧?相同的指针在结构本身中,它们只是普通的 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()

但这并没有改变什么。 :(

怎么办?

最佳答案

请注意,在 Debug模式下,编译器会在每个函数上绑定(bind)堆栈中的许多字节,
捕获缓冲区溢出错误。

0043E003  sub         esp, 0E4h ; < -- bound 228 bytes
...
0043E00D  lea         edi,[ebp-0E4h] 
0043E013  mov         ecx, 39h 
0043E018  mov         eax, 0CCCCCCCCh ; <-- sentinel
0043E01D  rep stos    dword ptr es:[edi] ; <-- write sentinels

编辑: OP Harvey 找到了打开/关闭堆栈探测器的编译指示。

check_stack

Instructs the compiler to turn off stack probes if off (or –) is specified,
or to turn on stack probes if on (or +) is specified.


#pragma check_stack([ {on | off}] )
#pragma check_stack{+ | –}

更新 : 嗯,探针是另一个故事,因为它看起来。
试试这个: /GZ (Enable Stack Frame Run-Time Error Checking)

关于visual-c++ - 为什么每次递归都使用这么多的堆栈空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2490923/

相关文章:

c++ - 给定一定的固定平台,sizeof 是否可以为同一类型返回不同的大小?

C++ 运行可执行文件并将输出通过管道传输到文件

c++ - 使列表控件中的单个项目可编辑(C++、MFC)

c++ - 有没有办法做一个循环堆栈?

html - 图 slider "Stacks"

c++ - 确认此标准库错误与 MSVC 2015 RC 中的分配器有关

c++ - 映射/设置迭代器不可递增映射/设置迭代器不可递增

c++ - 看似基本的C++问题

visual-c++ - 如何检测CListCtrl选择更改?

c - ) 堆栈程序中的预期错误