如何使用 Dtrace 在 Solaris 10 上检查 malloc?

Posted

技术标签:

【中文标题】如何使用 Dtrace 在 Solaris 10 上检查 malloc?【英文标题】:how to use Dtrace to check malloc on Solaris 10? 【发布时间】:2013-12-13 05:58:32 【问题描述】:

我遇到一个关于内存使用的麻烦错误,所以我想在 Solaris 10 上使用 Dtrace 来检查 malloc 和 free。

我使用以下命令

dtrace -l | grep malloc  

输出是:

7000        fbt              unix                       prom_malloc entry
7001        fbt              unix                       prom_malloc return
7141        fbt           genunix                       cacl_malloc entry
7142        fbt           genunix                       cacl_malloc return
12319        fbt           genunix                   rmallocmap_wait entry
12320        fbt           genunix                   rmallocmap_wait return
13078        fbt           genunix                      rmalloc_wait entry
13079        fbt           genunix                      rmalloc_wait return
13526        fbt           genunix                        rmallocmap entry
13527        fbt           genunix                        rmallocmap return
16846        fbt           genunix                           rmalloc entry
16847        fbt           genunix                           rmalloc return
25931        fbt             tmpfs                      tmp_memalloc entry
25932        fbt             tmpfs                      tmp_memalloc return  

好像没有malloc。

我检查了 Solaris 内部,发现 malloc 调用 sbrk。所以我使用以下命令:

dtrace -l | grep sbrk

但是什么也没找到。

那么

【问题讨论】:

我猜这个工具对你有用:theunixshell.blogspot.com/2013/11/… @Vijay:非常感谢您的 cmets,它是一个非常酷的工具! @Vijay:你愿意打开你工具的源代码吗? 给我发邮件 bvsarathi@gmail.com 或用您的电子邮件在博客上发表评论 【参考方案1】:

已经有各种工具实现了在 Solaris 下识别内存泄漏所需的逻辑,

libumem & mdb (UMEM_DEBUG=default UMEM_LOGGING=transaction LD_PRELOAD=libumem.so.1 然后mdb's ::findleaks) dbx (check -leaks)

如果您仍想采用dtrace 方式,您需要使用 pid 提供程序跟踪您怀疑泄漏内存的进程。您使用dtrace -l 搜索了内核探测器,但什么也没找到,但这是预期的,因为内核没有实现mallocbrk。它们是位于 C 标准库中的用户态函数。

此脚本将跟踪程序的每个 mallocfree 调用:

dtrace -qn '
pid$target:libc:malloc:entry 
        self->size=arg0;

pid$target:libc:malloc:return /self->size/ 
        printf("malloc(%d)=%p\n",self->size,arg1);
        self->size=0;

pid$target:libc:free:entry 
        printf("free(%p)\n",arg0);

' -c program_to_trace

如需更深入的示例,请查看http://ewaldertl.blogspot.fr/2010/09/debugging-memory-leaks-with-dtrace-and.html 和http://www.joyent.com/blog/bruning-questions-debugging

【讨论】:

您介意解释一下为什么返回指针在 arg1 而不是 arg0 中吗?我在 dtrace 上很绿色,但对于 syscall::open:return 之类的东西,文件描述符位于 arg0 @genghiskhan 这是设计使然。我正在使用 pid 提供程序,它的行为与您所指的系统调用提供程序不同。使用 pid 提供程序 A return probe fires when the traced function returns or makes a tail call to another function. The value for arg0 is the offset in the function of the return instruction; arg1 holds the return value.。请注意,对于系统调用提供程序,返回值在 arg0 和 arg1 中。 太棒了。感谢您的精彩解释。【参考方案2】:

例如,为了使用 dtrace 跟踪所有 malloc 调用,通过打印每个分配,您将编写(在本例中为名为 trace-malloc.d 的文件)如下脚本:

#!/usr/sbin/dtrace -s

    pid$1::malloc:entry
    
        self->trace = 1;
        self->size = arg0;
    

    pid$1::malloc:return
    /self->trace == 1/
    
        /* log the memory allocation */
        printf("<__%i;%Y;%d;malloc;0x%x;%d;\n", i++, walltimestamp, tid, arg1, self->size);
        ustack(50);
        printf("__>\n\n");

        self->trace = 0;
        self->size = 0;
    

然后通过传递您要跟踪的进程的进程ID来调用它, 例如:

./trace-malloc.d 12345

在复杂的程序中,内存分配和取消分配非常频繁,因此我编写了一个小程序来帮助我使用 dtrace 识别内存泄漏。跟踪 malloc / calloc / realloc 和 free 的每个内存操作,然后分析程序读取并处理所有跟踪并指出可疑的内存泄漏,还使用各种启发式方法指出强烈怀疑的内存泄漏。有兴趣的可以看这里:

https://github.com/ppissias/DTLeakAnalyzer.

【讨论】:

仅仅链接到您自己的库或教程并不是一个好的答案。链接到它,解释它解决问题的原因,提供如何解决问题的代码/过程,并否认你编写了它,这样可以得到更好的答案。见:What signifies “Good” self promotion? @Shree 帖子以“我已经写过”开头。那么,这不是一个明确的声明是谁编写了这个工具吗? @AdrianW 我总是想象没有链接的答案。如果没有链接,它的地址是一个问题,链接仅供参考,我没有标记答案。 您好,感谢您对回复的反馈,我已相应地对其进行了更改,以包括对问题的回答。目的是帮助遇到同样问题的其他人,因为不久前我还在使用 dtrace 搜索可用工具。

以上是关于如何使用 Dtrace 在 Solaris 10 上检查 malloc?的主要内容,如果未能解决你的问题,请参考以下文章

哪些 DTrace 脚本值得在 Solaris 上测试和分析 Java 程序

Oracle Solaris 上的 dtrace java API?

如何使用 dtrace 显示每个进程消耗的微秒 cpu?

我们可以使用 dtrace 对每个内核进行分析吗?

如何用 D 语言正确打印 uint64_t (dtrace)

用于跟踪库 API 的 Solaris 工具