2

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

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

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

我无法找出这种访问冲突发生在哪里,或者在哪里删除了一些临时对象以导致这些错误指针(我在使用它之前检查了每个指针),但是该死的,我在这里达到了我的极限。

那么,如何调试不可能的事情......一个带有蹩脚的调试器调用堆栈的随机崩溃?提前感谢您的耐心和善意的帮助!

4

2 回答 2

1

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

于 2012-12-12T16:05:51.813 回答
0

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

当然,现实世界并不完美,并且确实会出现错误。要调试内存损坏,您可以使用一些不错的工具,例如 valgrind,它至少可以缩小问题部分,以便您仔细查看。调试一个复杂的程序并不容易,如果你的调试器出错了,你需要大量的坚持。我发现一种有用的技术是选择性地启用或禁用某些模块,以缩小模块的范围。

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

int foo = factorial(3);

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

另一个重要的一点是始终维护一个跟踪文件,您的代码会在其中记录它正在做的事情。当程序崩溃时,跟踪文件通常可以帮助缩小问题范围。当然,您默认禁用跟踪,以免造成性能瓶颈。

于 2012-12-12T01:51:23.133 回答