我有一个庞大的C ++代码库。在某组数据上有堆栈溢出。如果我在Visual Studio调试器下运行程序,我得到一个调用堆栈30个不熟悉的函数 - 这些函数中的一个(或多个)在堆栈上创建了一个太大的对象,这导致堆栈耗尽。我看了所有的功能,没有什么明显的 - 没有像
char buffer[512 * 1024];
我虽然可以在每个函数的开头添加一个变量并转储该变量地址并重新编译,然后查看相邻函数之间的差异,但这需要大量的手工劳动。
如何快速识别在堆栈上创建过大对象集的函数并导致缓冲区溢出?
答案 0 :(得分:4)
如果你有一个堆栈跟踪(并且你应该能够得到一个),你可以访问这些帧的地址。
导致问题的一个函数应该导致帧指针的巨大飞跃。
如果没有,请检查堆栈大小,它可能只是太小了。
编辑:如何使用VC ++调试非显而易见的问题? (哼......我在Unix上编码:/)
Elan Rusking在他的2011 GDC presentation(PDF)中就调查发表了精彩的演讲。
堆栈指针(在x86上)存储在ESP
寄存器中。如果您查看反汇编并检查ESP
的更改,那么您应该能够看到哪个函数以较大的值递增/递减。
wikibooks上的示例:
mov eax, DWORD PTR SS:[esp]
add esp, 4
此add esp
是您要跟踪的内容。除非您使用的是VLA,否则添加/减去的值是硬编码的,因此很容易检查。
答案 1 :(得分:4)
您可以在Visual C ++中使用代码分析,它可以在更高版本中使用。如果函数使用高于某个限制的堆栈,则会生成警告(C6262)。您可以使用/analyze:stacksize
切换,其中stacksize
是您想要的限制。
答案 2 :(得分:2)
超出其堆栈分配的线程将引发异常。使用Microsoft Visual C ++中的__try
和__except
关键字可以捕获此异常。您可以将函数包装在此try-except块中,以查看它们是否导致堆栈溢出。