我们有一个复杂的程序,在重载输入(实际上是任何输入)上运行良好,没有实现多线程
我们用线程池实现了多线程,给定这些输入参数我得到了这些结果:
(注意:我说 没有错误 ,这意味着我已经使用valgrind -v
进行了测试,当我说 没有内存泄漏 ,这意味着我已经使用valgrind --leak-check=full -v
进行了测试。
valgrind -v
一起使用> 1名工人程序成功完成。此外,没有从valgrind打印错误,即ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
。 既然我没有从valgrind那里得到任何错误,我该怎么做才能在这个复杂而庞大的应用程序中找到内存损坏问题?
DevelopmentEnvironment:
Ubuntu,64bit,gcc版本:4.7.2和4.8.1(不同的计算机,更新版本的Ubuntu)。
答案 0 :(得分:11)
既然我没有从valgrind那里得到任何错误,我该怎么做才能在这个复杂而庞大的应用程序中找到内存损坏问题?
让我向您描述我在20世纪90年代在微软的JavaScript实现中发现内存泄漏的方法。
首先,我确保在我的程序的调试版本中,尽可能多的内存分配被路由到相同的帮助器方法。也就是说,我将malloc
,new
等重新定义为我自己编写的分配器的所有同义词。
该分配器只是一个围绕操作系统虚拟堆内存分配器的薄外壳,但它有一些额外的智能。它在块的开头和结尾分配了额外的内存,并用sentinel值,到目前为止的分配数量的线程安全计数以及所有分配的线程安全双向链表填充。 "免费"例程将验证双方的哨兵值仍然完好无损;如果没有,那么某处存在内存损坏。它会将块与链接列表取消链接并释放它。
在任何时候,我都可以按照分配顺序向内存管理器询问内存中所有未完成块的列表。卸载DLL时列表中剩余的任何项目都是内存泄漏。
这些工具使我能够非常轻松地实时查找内存泄漏和内存损坏。
答案 1 :(得分:3)
使用> 1名工人,我得到:a。通常堆损坏错误,b.double-free。 使用valgrind -v运行> 1名工人程序成功完成
基于上述症状,我认为您的程序中明显存在某种同步问题。看起来你的程序在线程之间共享堆内存地址,因此每当有一些数据争用时你就会遇到问题。
您还提到当您运行valgrind -v时,您的程序已成功完成。这表明您的程序存在同步问题,并且该程序也依赖于序列/时序。这些是最难找到的错误之一。我们还应该记住,在程序运行并执行错误之前,动态工具不会发出任何警告。我的意思是程序中可能存在问题,但是执行顺序(因为存在一些与时间相关的问题)确定工具是否会捕获那些失败。
话虽如此,我认为在大型程序中找不到这样的错误并没有减少方法。但是我强烈怀疑存在一些导致内存损坏/双重释放的数据竞争场景。因此,您可能希望使用 Helgrind 来检查/查找可能导致内存损坏的数据竞争/线程问题。
答案 2 :(得分:0)
请使用CORE DUMP :: [主要用于双重免费,glibc检测到的类型错误]
使用gcc -g选项编译程序以获取调试信息
它会显示核心文件的大小
它将设置核心文件的大小无限
现在运行你的程序,然后在你当前的目录中,一个文件将生成名为" core"
然后由GDB分析如下..
它会告诉你哪里有问题..
如果您发现任何困难,请写信给我......