我在Upstart init进程(pid 1)中有一个内存泄漏,我在调试它时有哪些选项?
编辑:建议我使用一些真正的工具,手动放置printfs或手工计算内存分配不会减少它。此外,抛出init核心并在其周围穿插并不是一个真正的选择。
UPD1: valgrind不起作用。将内核命令行上的/sbin/init替换为适当的val差使+ init魔术似乎不是一个选项,因为它试图访问smaps的/proc,但在运行init之前这些选项是不可用的。
UPD2: dmalloc也不工作(在ARM上不编译)。
发布于 2010-10-11 16:51:14
穷人的解决方案是只记录每一个调用malloc和free,然后梳理日志并寻找模式。
ld提供了一个非常棒的特性,可以在这里提供帮助。
--wrap=symbol对符号使用包装函数。对符号的任何未定义的引用将被解析为"__wrap_symbol“。对"__real_symbol“的任何未定义的引用都将被解析为符号。 这可用于为系统功能提供包装器。包装器函数应该称为"__wrap_symbol“。如果希望调用系统函数,则应该调用"__real_symbol“。 下面是一个简单的例子: void * __wrap_malloc (size_t c) { printf ("malloc与%zu\n调用“,c);返回__real_malloc (c);} 如果使用--包装malloc将其他代码链接到此文件,那么所有对"malloc“的调用都将调用函数"__wrap_malloc”。调用"__real_malloc“中的"__wrap_malloc”将调用真正的"malloc“函数。 您可能也希望提供一个"__real_malloc“函数,这样没有-wrap选项的链接就会成功。如果这样做,则不应该将"__real_malloc“的定义与”__wrap_malloc“放在同一个文件中;如果这样做,汇编程序可能会在链接器有机会将其包装为"malloc”之前解析调用。
更新
只是为了弄清楚这是如何有用的。
如下所示:
void*__wrap_malloc( size_t c )
{
void *malloced = __real_malloc(c);
/* log malloced with its associated backtrace*/
/* something like: <malloced>: <bt-symbol-1>, <bt-symbol-2>, .. */
return malloced
}
void __wrap_free( void* addr )
{
/* log addr with its associated backtrace*/
/* something like: <addr>: <bt-symbol-1>, <bt-symbol-2>, .. */
__real_free(addr);
}-g)重新编译upstart,这样您就可以得到一些不错的回溯。如果您愿意,仍然可以优化(-O2/-O3)代码。LD_FLAGS --wrap=malloc,--wrap=free。
现在,Upstart在任何地方调用malloc,符号将被神奇地解析为您的新符号__wrap_malloc。漂亮的是,这对于编译后的代码都是透明的,因为它发生在链接时。
这就像闪鸣或仪器化没有任何混乱。malloceds和addrs。几个注意事项:
--wrap=symbol特性不适用于实际上是宏的函数名。所以要小心#define malloc nih_malloc。这就是libnih需要使用--wrap=nih_malloc和__wrap_nih_malloc的地方。发布于 2010-10-11 10:32:37
您可以通过连接malloc/free调用,并计算分配的字节数和每次释放的字节数来自行检测内存分配。
发布于 2010-10-11 10:52:32
您也可以不作修改地使用init,但是可以创建一个包装器,它将MALLOC_CHECK环境变量设置为1或更高。这将让您看到一些内存分配诊断。
一个变化是稍微修改init源代码,以便在使用malloc之前尽早设置环境变量本身。
您还可以按照AmineK的建议,将调试代码添加到init源代码本身。
https://stackoverflow.com/questions/3887723
复制相似问题