-1

我从 2 年前开始编写游戏。有时一些内存错误(即:一个函数返回垃圾而不是它应该返回的内容,或者只在 Linux 上发生的崩溃,而在 GDB 或 Windows 上永远不会发生)似乎是随机发生的。也就是说,我尝试修复它,几个月后,同样的错误再次困扰着我。

有一个软件(不是 Valgrind,我已经试过了......它没有找到错误)可以帮助我解决这个问题?或者解决这些错误的方法?我想永久修复它们。

4

5 回答 5

3

在 Windows 上,您可以在生产环境中自动捕获崩溃异常,并在调试器下将其分析为好像错误发生在您的开发人员 PC 上一样。这是使用“小型转储”文件完成的。您基本上使用 Windows“dbghelp.dll”DLL 来生成线程堆栈、部分或全部堆、寄存器值、加载的模块以及导致崩溃的未处理异常的副本。您可以在 MS Visual Studio 调试器中启动这个“.dmp”文件,就像它是一个可执行文件一样,它会准确地显示崩溃发生的位置。

您可以为未处理的异常设置陷阱,并将迷你转储文件的创建委托给该陷阱中的 dbghelp.dll。您需要保留使用已部署的二进制文件生成的“.pdb”文件,以将内存地址与源代码位置匹配,以获得更好的调试体验。这个主题太深了,无法完全涵盖 请参阅Microsoft关于此 DLL 的文档。

您确实需要能够将 .dmp 文件从崩溃的 PC 复制到您的开发环境中以对其进行全面调试。如果您与您的用户有不干涉的关系,您将需要选择通过 Internet 使用单独的实用程序应用程序“电话回家”将 .dmp 文件传输到您可以访问它的位置。生成 .dmp 文件后,您可以从未处理的异常陷阱中启动应用程序。为了用户隐私,您应该让用户选择是否这样做。

于 2010-02-10T04:23:53.217 回答
1

Totalview 调试器(商业软件)可能会捕获崩溃。

Purify(商业软件)可以帮助您发现内存泄漏。

您的代码编译时是否没有编译器警告?你跑 lint 了吗?

于 2010-02-10T07:26:46.383 回答
1

您可以尝试的一件事是在您的项目中使用 Hans Boehm GC。它可以用作泄漏检测器,允许您删除可疑的语句free()delete语句,并轻松查看它们是否导致内存泄漏。

于 2010-02-10T23:22:23.363 回答
0

AFAIK,Windows 中的 Boundscheck 做得很好。在我的一个项目中,它发现了一些非常奇怪的错误。

于 2010-02-10T06:04:10.237 回答
0

为了在我自己的项目(在 Windows 上)中避免这种情况,我编写了自己的内存分配器,简称为 VirtualAlloc 和 VirtualFree。它为每个请求分配一个额外的页面,将其与最后一页的左侧对齐,并用于VirtualProtect在访问最后一页时生成异常。这会在现场检测到越界访问,甚至只是读取。

免责声明:我绝不是第一个有这个想法的人。

例如,如果页面是 4096 字节,并且new int[1]被调用,分配器将:

  1. 分配 8192 字节(需要 4 字节,也就是一页,额外的保护页使总数达到 2 页)
  2. 将最后一页标记为不可访问
  3. 确定要返回的地址(最后分配的页面从 4096 开始... 4096 - 2 = 4092)

以下代码:

main() {
    int *array = new int[10];
    return array[10];
}

然后会当场产生访问冲突。

它还有一个(编译时)选项来检测超出分配左侧的访问(即,array[-1]),但这类错误似乎很少见,所以我从未使用过该选项。

于 2010-02-10T23:19:29.840 回答