【问题标题】:How to analyze memory leak from coredump如何分析 coredump 的内存泄漏
【发布时间】:2014-12-22 08:24:35
【问题描述】:

我想通过核心文件分析来分析内存泄漏。

我已经编写了示例代码来注入内存泄漏并使用 gcore 命令生成核心文件。

#include <stdlib.h>
#include <unistd.h>
void fun()
{
  int *ptr = new int(1234);
}
int main()
{
  int i=0;
  while(i++<2500)
  {
    fun();
}
sleep(360);
return 0;
}

查找进程ID

ayadav@ajay-PC:~$ ps -aef |grep over  
ajay      8735  6016  0 12:57 pts/2    00:00:00 ./over  
ayadav    8739  4659  0 12:57 pts/10   00:00:00 grep over  

并生成核心

ayadav@ajay-PC:~$ sudo gcore 8735
[sudo] password for ayadav:
0x00007fbb7dda99a0 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:81
81      ../sysdeps/unix/syscall-template.S: No such file or directory.
Saved corefile core.8735

我从核心文件中找到了以下常见模式(如stackoverflow另一个线程Is there a way to locate which part of the process used the most of the memory, only looking at a generated core file?上的建议)

ayadav@ajay-PC:~$ hexdump core.6015 | awk '{printf "%s%s%s%s\n%s%s%s%s\n", $5,$4,$3,$2,$9,$8,$7,$6}' | sort | uniq -c | sort -nr | head
6913 0000000000000000  
2503 0000002100000000  
2501 000004d200000000  
786 0000000000007ffc  
464  
125 1ccbc4d000007ffc  
 92 1ca7ead000000000  
 91 0000000200007ffc  
 89 0000000100007ffc  
 80 0000000100000000  

以下两个地址疑似一个

2503 0000002100000000  
2501 000004d200000000  

核心文件有以下重复模式

0003560 0000 0000 0021 0000 0000 0000 04d2 0000  
0003570 0000 0000 0000 0000 0000 0000 0000 0000  
0003580 0000 0000 0021 0000 0000 0000 04d2 0000  
0003590 0000 0000 0000 0000 0000 0000 0000 0000  
00035a0 0000 0000 0021 0000 0000 0000 04d2 0000  
00035b0 0000 0000 0000 0000 0000 0000 0000 0000  
00035c0 0000 0000 0021 0000 0000 0000 04d2 0000  
00035d0 0000 0000 0000 0000 0000 0000 0000 0000  
00035e0 0000 0000 0021 0000 0000 0000 04d2 0000  
00035f0 0000 0000 0000 0000 0000 0000 0000 0000  
0003600 0000 0000 0021 0000 0000 0000 04d2 0000  
0003610 0000 0000 0000 0000 0000 0000 0000 0000  
0003620 0000 0000 0021 0000 0000 0000 04d2 0000  
0003630 0000 0000 0000 0000 0000 0000 0000 0000  
0003640 0000 0000 0021 0000 0000 0000 04d2 0000

但我不太清楚如何从 gdb info address 或 x 等命令访问它。 谁能告诉我如何将符号信息从二进制格式转换?

【问题讨论】:

标签: c coredump gcore


【解决方案1】:

1 - 可以使用核心转储来评估内存泄漏。我举了一个 c++ 示例:

class Base  
{  
public:  
    virtual void fun(){}  
    virtual void xyz(){}  
    virtual void lmv(){}  
    virtual void abc(){}  
};  

class Derived: public Base  
{  
public:  
    void fun(){}  
    void xyz(){}  
    void lmv(){}  
    void abc(){}  
};  

void fun()  
{  
    Base *obj  = new Derived();  
}  
int main()  
{  
    for(int i = 0; i < 2500;i++)
    {
        fun();
    }
    sleep(3600);
    return 0; 
}

2 - 使用 gcore 命令创建核心

3 - 从核心文件中搜索重复的模式。

ayadav@ajay-PC:~$ hexdump core.10639 | awk '{printf "%s%s%s%s\n%s%s%s%s\n", $5,$4,$3,$2,$9,$8,$7,$6}' | sort | uniq -c | sort -nr  | head
   6685 0000000000000000  
   2502 0000002100000000  
   2500 004008d000000000  
    726 0000000000007eff  
    502   
    125 2e4314d000007eff  
     93 006010d000000000  
     81 0000000100007eff  
     80 0000000100000000  
     73 0000000000000001  

0000002100000000004008d000000000 是重复模式

4 - 检查每个 qword 是什么?

(gdb) info symbol ...
(gdb) x ...

示例:

(gdb) info symbol 0x4008d000
No symbol matches 0x4008d000.
(gdb) info symbol 0x4008d0
vtable for Derived + 16 in section .rodata of /home/ayadav/virtual

5 - 可能最常见的 vtable 必须与内存泄漏有关,即 Derived vtable。

注意:我同意 coredump 分析不是查找内存泄漏的最佳实践。内存泄漏可以通过 valgrind 等不同的静态和动态工具找到。

【讨论】:

  • 我喜欢 Unix 的思维方式,但我不得不说应该可以弄清楚核心文件中当前处于活动状态的分配类型......在快速浏览 Google 之后core analyzer 出现了。
【解决方案2】:

我认为没有办法确定进程是否导致内存泄漏或不直接查看核心转储。事实上,没有所谓的内存泄漏,我们不能在不知道程序员编写代码的意图的情况下发表评论。话虽如此,您可以通过查看核心转储的大小来了解。您可以生成多个转储,例如,一个在初始运行后,一个在长时间运行后,如果您发现大小差异很大,可以猜测可能出现问题。但同样,内存可以用于生产目的。

对于内存泄漏的实际分析和跟踪,应该使用 memtrack、valgrind 等工具在 malloc 和 free 上添加包装器,以提供有关每个 alloc 和 free 的额外信息。

更新:

当您正在寻找十六进制分析时,我可以看到以下内容: 您的每一行都是 16 个字节,并在两行中​​重复。即一个块 32 个字节。 0x4D2 是十进制的 1234。所以,你的数据就在那里。您的一个分配块可能是 32 个字节。在每个 'new()' 之后检查并打印十六进制地址,并比较以查看您是否观察到 32 个字节的间隙,然后对其进行解释。

【讨论】:

  • 嗨,乔,stackoverflow.com/questions/8710404/… 上的回答。可以从 coredump 中找到内存泄漏。我同意我可以使用 Valgrind 之类的工具,但据我所知,我想从核心文件中进行分析。
  • 根据您的要求更新答案。但我认为这不是调试内存泄漏的正确方法。
  • 嗨乔,非常感谢您的建议。是的 alloc 块是 32 字节的间隙。 0x12c4010 0x12c4030 0x12c4050 0x12c4070 0x12c4090 0x12c40b0 0x12c40d0 0x12c40f0 0x12c4110 0x12c4130 0x12c4150 0x12c4170 如何
  • “事实上,没有所谓的内存泄漏本身,我们不能在不知道程序员编写代码的意图的情况下发表评论。”我会说这有点正确,但如果有人动态分配了他们不再保留任何指针的内存,就像问题的例子一样,那么它就是内存泄漏。
猜你喜欢
  • 2013-05-24
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多