我用C编写了一个函数,当它被调用时,会立即导致堆栈溢出。
原型:void dumpOutput( Settings *, char **, FILE * );
呼叫线路:dumpOutput( stSettings, sInput, fpOut );
在调用它时,stSettings
已经是指向Settings
结构的指针,sInput
是动态分配的2D阵列,fpOut
是FILE *
。它一直到达呼叫线路,没有任何错误,没有内存泄漏等。
实际的函数相当长,我认为不值得在这里分享,因为代码进入函数时会发生溢出(我认为称为序言部分)
我曾尝试使用伪变量直接从main()
调用相同的函数,以检查传递的参数是否有任何问题,但它仍然抛出堆栈溢出条件。
调用函数时,chkstk.asm
会产生错误。这个asm文件(根据其中的注释)试图探测堆栈,以检查/分配被调用函数的内存。它只是不断跳到Find next lower page and probe
部分,直到发生堆栈溢出。
dumpOutput
中的局部变量也不是内存野兽,只有6个整数和2个指针。
代码在进入此函数时使用的内存为60936K,在发生堆栈溢出时增加到61940K。这些内存的大部分进入sInput
。这是错误的原因吗?我不这么认为,因为只传递了它的指针。其次,我不明白dumpOutput
为什么要在堆栈上分配1004K内存?
我在这里完全不知所措。如有任何帮助,我们将不胜感激。
提前谢谢。
根据设计,生成堆栈溢出异常是_chkstk()的作业。您可以通过查看生成的机器代码来诊断它。进入该功能后,右键单击编辑窗口,然后单击"转到反汇编"。你应该看到类似的东西:
003013B0 push ebp
003013B1 mov ebp,esp
003013B3 mov eax,1000D4h ; <== here
003013B8 call @ILT+70(__chkstk) (30104Bh)
通过EAX寄存器传递的值是重要的值,这是函数所需的堆栈空间量。Chkstk然后通过探测堆栈的页面来验证它实际上是可用的。如果您看到它重复循环,那么代码中EAX的值就会很高。和我的一样,它保证消耗堆栈的所有字节。还有更多。这就是它所保护的,你通常会得到一个访问违规异常。但不能保证,您的代码可能会意外地写入到属于堆的映射页。这将产生一个极其难以诊断的错误。Chkstk()可以帮助你在沮丧时找到这些错误。
我只是用这个小小的测试功能:
void test()
{
char kaboom[1024*1024];
}
我们看不到您的,但异常表明您要么有一个大数组作为局部变量,要么将一个大值传递给_alloca()。通过从堆中分配该数组来修复此问题。
很可能是堆栈损坏或递归错误,但很难在没有看到任何代码的情况下回答