调试难以发现的异常

时间:2012-12-12 01:22:37

标签: c++ visual-studio-2010 debugging

首先,感谢您抽出宝贵时间查看我的问题和帮助。我注意到很多提问者在这里表现出很少或根本没有欣赏,但我真诚地感谢这里的帮助和社区:)

我为一个没有源代码的应用程序(这是一个视频游戏)编写了一个C ++插件(被数百个源文件攻击)。换句话说,我只有我的插件的源代码,但不是游戏。现在,在我的插件中的数千行中,有些东西导致游戏引擎抛出(可能是访问冲突),我不知道在哪里。到调试器中断时,堆栈已损坏,我得到的只是我没有源代码的DLL的十六进制地址(但是我的DLL肯定会发生异常)。我尝试了一切......我似乎无法找到异常发生的地方。有时调试器指向“内存重定位”功能(我从未在我的插件中使用过),有时它指向引擎的GameFrame(),有时它指向损坏回调(所有这些只是一个不同的成员函数)类)。

我几乎尝试了所有的东西......我用谷歌搜索了几个小时试图找出如何使用其他调试器,如WinDbg和Microsoft Application Verifier。我试图注释掉调试器指向的一个或另一个,或两者,但它仍然崩溃。我甚至将OUTPUT("The name of the last executed function is: %s", __FUNCTION__)插入到我的应用程序中的每个函数中,希望能够精心地捕获最后一个函数,但似乎任何类型的I / O都会阻止异常因某种原因发生...并且10分钟的调试和崩溃发生在一些随机的最后执行函数。

我无法找到这种访问违规发生的位置或删除某些临时对象导致这些错误指针的地方(我在使用它之前检查每个指针),但该死的,我在这里达到我的极限。< / p>

那么,如何调试不可能的...随机崩溃与糟糕的调试器调用堆栈?在此先感谢您的耐心和亲切的帮助!

2 个答案:

答案 0 :(得分:1)

我的建议:尝试不同的调试器(非MS),他们捕获不同的东西。 我的经验:一个程序我有源代码和完整的调试符号破坏堆栈,VS和WinDbg可以帮助但是Ollydbg注释一个非字符串var,其值为“r for pattern。”,所以我在这个变量上覆盖了一些字符串缓冲区。此外,Ollydbg可以选择以困难的方式遍历堆栈(不使用dbghelp.dll)

答案 1 :(得分:0)

根据我的经验,古老的格言“预防胜于治疗”非常重要。最好通过遵循良好的软件开发实践(单元测试,回归,代码审查等)来防止错误蔓延,而不是在错误出现后再进行处理。

当然,现实世界并不完美,而且确实会出现错误。要调试内存损坏,你有一些很好的工具,比如valgrind,它至少可以缩小问题部分,让你仔细看看。调试复杂的程序并不容易,如果调试器抛出,则需要大量的持久性。我觉得有用的一种技术是有选择地启用或禁用某些模块,以缩小模块的问题。

有时您需要使用“引用透明度”来卸载某些模块。为了给你一个精简的例子,请考虑:

int foo = factorial(3);

如果我怀疑此代码中存在问题(并且调试器在我看到调用堆栈之前崩溃),我必须尝试删除此代码,并查看问题是否仍然存在。但是,foo可能会在以后使用,所以我不能删除它。相反,我可以将其替换为int foo = 6;并继续。

另一个重要的一点是始终维护一个跟踪文件,您的代码会在其中记录它正在执行的操作。当程序崩溃时,跟踪文件通常可以帮助缩小问题范围。当然,默认情况下禁用跟踪,因此不会导致性能瓶颈。