有没有办法找到进程的哪个部分使用了大部分内存,只查看生成的核心文件?

Kir*_*rov 15 c++ unix linux gdb memory-leaks

我有一个进程(每次都由看门狗启动,由于某种原因停止),通常使用大约200MB的内存.有一次,我看见它吃起来记忆-约1.5-2GB,这无疑意味着在引号中的"内存泄漏"的地方("内存泄漏"内存使用情况,因为这是不是一个真正的内存泄漏-样分配的内存,永远不会被释放和无法访问 - 请注意,只使用智能指针.所以,我想一些巨大的容器(我没找到)或类似的东西)

后来,由于内存使用率很高,并且生成了核心转储,该进程崩溃了 - 大约2GB.但问题是,我无法重现这个问题,所以valgrind在这里不会有所帮助(我猜).它很少发生,我不能"抓住"它.

所以,我的问题是 - 有没有办法,使用exe和核心文件,找到进程的哪个部分,已经使用了大部分内存?

我看了一下核心文件gdb,没什么不寻常的.但核心很大,所以必须有一些东西.有没有一种聪明的方法可以理解发生了什么,或者只是猜测可能会有所帮助(但对于这样的大型程序,12个线程,大约50-100(可能更多)类等等)

这是一个C++在RHEL5U3上运行的应用程序.

Evg*_*uev 12

以十六进制格式打开此coredump(如bytes/words/dwords/qwords).从文件中间开始尝试注意任何重复模式.如果发现任何问题,请尝试确定起始地址和某些可能的数据结构的长度.使用此结构的长度和内容,尝试猜测它可能是什么.使用该地址,尝试找到一些指向此结构的指针.重复,直到你来到堆栈或一些全局变量.在堆栈变量的情况下,您将很容易知道该链的起始函数.在全局变量的情况下,您至少知道它的类型.

如果你在coredump中找不到任何模式,那么泄漏的结构很可能很大.只需将您在文件中看到的内容与程序中所有大型结构的可能内容进行比较.

更新

如果您的coredump具有有效的调用堆栈,则可以从检查其功能开始.搜索任何异常的东西.检查调用堆栈顶部附近的内存分配是否请求不太多.检查调用堆栈函数中是否存在可能的无限循环.

单词" 只使用智能指针 "吓坏了我.如果这些智能指针的重要部分是共享指针(shared_ptr,intrusive_ptr,...),而不是搜索大容器,那么搜索共享指针周期是值得的.

更新2

尝试确定堆在corefile(brkvalue)中的结束位置.在gdb下运行coredumped进程并使用pmap命令(来自其他终端).gdb也应该知道这个值,但是我不知道怎么问它...如果大多数进程的内存在上面brk,你可以通过大内存分配限制你的搜索(很可能是std :: vector).

为了提高在现有coredump的堆区域中发现泄漏的可能性,可以使用一些编码(我自己不做,只是一个理论):

  • 读取coredump文件,将每个值解释为指针(忽略代码段,未对齐的值和指向非堆区域的指针).对列表进行排序,计算相邻元素的差异.
  • 此时,整个存储器被分成许多可能的结构.计算结构大小的直方图,删除任何无关紧要的值.
  • 计算这些指针所属的指针和结构的地址差异.对于每个结构大小,计算指针位移的直方图,再次删除任何无关紧要的值.
  • 现在您有足够的信息来猜测结构类型或构建结构的有向图.查找此图的源节点和周期.您甚至可以将此图形可视化为"列表"冷"存储区域".

Coredump文件elf格式.只需要从其标题开始和大小的数据段.要简化过程,只需将其读作线性文件,忽略结构.

  • 运行`strings core`也可能提供一些线索. (2认同)