我从 2 年前开始编写游戏。有时一些内存错误(即:一个函数返回垃圾而不是它应该返回的内容,或者只在 Linux 上发生的崩溃,而在 GDB 或 Windows 上永远不会发生)似乎是随机发生的。也就是说,我尝试修复它,几个月后,同样的错误再次困扰着我。
有一个软件(不是 Valgrind,我已经试过了......它没有找到错误)可以帮助我解决这个问题?或者解决这些错误的方法?我想永久修复它们。
在 Windows 上,您可以在生产环境中自动捕获崩溃异常,并在调试器下将其分析为好像错误发生在您的开发人员 PC 上一样。这是使用“小型转储”文件完成的。您基本上使用 Windows“dbghelp.dll”DLL 来生成线程堆栈、部分或全部堆、寄存器值、加载的模块以及导致崩溃的未处理异常的副本。您可以在 MS Visual Studio 调试器中启动这个“.dmp”文件,就像它是一个可执行文件一样,它会准确地显示崩溃发生的位置。
您可以为未处理的异常设置陷阱,并将迷你转储文件的创建委托给该陷阱中的 dbghelp.dll。您需要保留使用已部署的二进制文件生成的“.pdb”文件,以将内存地址与源代码位置匹配,以获得更好的调试体验。这个主题太深了,无法完全涵盖 请参阅Microsoft关于此 DLL 的文档。
您确实需要能够将 .dmp 文件从崩溃的 PC 复制到您的开发环境中以对其进行全面调试。如果您与您的用户有不干涉的关系,您将需要选择通过 Internet 使用单独的实用程序应用程序“电话回家”将 .dmp 文件传输到您可以访问它的位置。生成 .dmp 文件后,您可以从未处理的异常陷阱中启动应用程序。为了用户隐私,您应该让用户选择是否这样做。
Totalview 调试器(商业软件)可能会捕获崩溃。
Purify(商业软件)可以帮助您发现内存泄漏。
您的代码编译时是否没有编译器警告?你跑 lint 了吗?
您可以尝试的一件事是在您的项目中使用 Hans Boehm GC。它可以用作泄漏检测器,允许您删除可疑的语句free()
或delete
语句,并轻松查看它们是否导致内存泄漏。
AFAIK,Windows 中的 Boundscheck 做得很好。在我的一个项目中,它发现了一些非常奇怪的错误。
为了在我自己的项目(在 Windows 上)中避免这种情况,我编写了自己的内存分配器,简称为 VirtualAlloc 和 VirtualFree。它为每个请求分配一个额外的页面,将其与最后一页的左侧对齐,并用于VirtualProtect
在访问最后一页时生成异常。这会在现场检测到越界访问,甚至只是读取。
免责声明:我绝不是第一个有这个想法的人。
例如,如果页面是 4096 字节,并且new int[1]
被调用,分配器将:
以下代码:
main() {
int *array = new int[10];
return array[10];
}
然后会当场产生访问冲突。
它还有一个(编译时)选项来检测超出分配左侧的访问(即,array[-1]),但这类错误似乎很少见,所以我从未使用过该选项。