有没有办法知道在Linux中传递给__free_hook的指针的大小?

时间:2013-03-12 17:31:25

标签: c linux malloc hook free

我想跟踪大型应用程序当前分配的内存量。

我发现我可以在malloc / free / realloc周围安装钩子以拦截内存分配调用:

http://man7.org/linux/man-pages/man3/malloc_hook.3.html

所以我要跟踪的是分配的总字节数 - 释放的总字节数。

现在的问题是free只接受指针而不是大小。

In可以在我的malloc钩子中创建我自己的map或hashmap,它跟踪为该指针分配了多少内存,但这会导致相当多的开销。

有没有办法(即使它有点像黑客)在调用free时使用ptr大小的Linux(64位)(使用默认的g ++ malloc)?

4 个答案:

答案 0 :(得分:5)

linux man malloc_usable_size

  

malloc_usable_size()返回可用的字节数   动态分配的缓冲区ptr,可能大于   请求的大小(但保证至少与大小一样大   请求成功)。通常,您应该存储   请求分配大小而不是使用此功能。

答案 1 :(得分:3)

这不是你问题的直接答案,但看到你对总分配内存感兴趣,那么这就是解决方案:

我认为你最感兴趣的是它返回的结构的uordblks字段。

请注意,这不是标准的POSIX功能,但我想这就是你对这种非标准内省所期望的......

答案 2 :(得分:1)

内存块的大小通常存储在指针下方。虽然这是一个黑客攻击(你说我可以......),但是我的Linux机器上运行了以下代码:

#include <stdio.h>
#include <stdlib.h>

int main(){
int *p, n=123;
p = (int*)malloc(n*sizeof(int));
printf("allocated %d bytes for p\n", n*sizeof(int));
printf("p[-2] : %d \n", *(p-2));
printf("malloc_useable_size(p) : %d\n", malloc_usable_size(p));
free(p);
}

它产生的输出是:

allocated 492 bytes to p
p[-2] : 513
malloc_useable_size(p): 504

请注意,p [-2]中的大小并不完全是492 - 由于内务和边界对齐等原因,还有一些额外的空间用完。

另请注意 - 这适用于gcc编译器;但g++抱怨指针转换,我没有声明malloc_useable_size()。在看到@ fanl的回答后,我出于好奇而添加了这一行。在看到@OliCharlesworth的答案之后,我还在mallinfo的输出中玩了一下。

你可以改变n的值,你会看到事情非常吻合 - 例如,如果你从n(在我的上面的代码中)从100到119步,那么感兴趣的不同变量的值如下:

  n | p[-2] | usable | uordblks
----+-------+--------+---------
100    417     408       416
101    417     408       416
102    417     408       416
103    433     424       432
104    433     424       432
105    433     424       432
106    433     424       432
107    449     440       448
108    449     440       448
109    449     440       448 
110    449     440       448
111    465     456       464   
112    465     456       464
113    465     456       464
114    465     456       464
115    481     472       480
116    481     472       480
117    481     472       480
118    481     472       480
119    497     488       496 

usablep[-2]之间以及1p[-2]之间的uordblks之间始终存在9的差异。 p[-2]方法的优势在于它可以准确地告诉您要求的内容 - 指针的大小。其他电话实际上可能会告诉您真正想要的内容 ...

PS很可能对于非常大的内存块,您需要查看long integer生成的*((long int*)(p)-1)。这给了我一个漂亮的宏的灵感:

#define PSIZE(a) (*((long int*)(a)-1))

然后你可以用

找出任何指针的大小
printf("my pointer size is %ld\n", PSIZE(myPointer));

无需担心指针的类型。我确认这适用于不同类型的指针,对于块&gt; 4G。显然你可以决定在宏中减去1,这样数字就与mallinfo()完全一致。

编辑:在this earlier question的一个答案中给出了对指针下方存储内容的更完整描述。这表明我观察到的“+1”实际上是由于存储在LSB中的标志。正确的方法是将结果与~3一起清除两个LSB,然后从结果中减去(long int *)的大小(实际上原始答案减去2 * sizeof(unsigned long int)但我认为是错误):

#define PSIZE(a) ((*((long int*)(a)-1))&~3 - sizeof(long int*))

链接的答案强烈建议仅将其用于调试,而不是将其用于实际代码。我不得不重复这个警告。

答案 3 :(得分:0)

你需要在malloc中安装一个钩子来构建一个缓存所请求块大小的指针表,然后当你空闲时,在上一个malloc项目数据库中搜索指针。

通过这种方式,您将知道减少当前分配的堆总和(如果这是您的目标),并且将有一个方便的位置来列出仍在内存中的堆的所有“区域”。