2

我想跟踪大型应用程序当前分配了多少内存。

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

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

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

现在的问题是 free 只需要一个指针而不是一个大小。

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

有什么方法(即使它有点黑客)在 Linux(64 位)上获得调用 free 时 ptr 的大小(使用默认的 g++ malloc)?

4

4 回答 4

5

linux man malloc_usable_size

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

于 2013-03-12T17:37:40.017 回答
2

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

我认为您将对uordblks它返回的结构字段最感兴趣。

请注意,这不是标准的 POSIX 函数,但我想这就是您对像这样的非标准内省所期望的......

于 2013-03-12T17:38:50.530 回答
1

内存块的大小通常存储在指针下方。虽然这是一个 hack(你说我可以......),但以下代码在我的 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 的回答后,我出于好奇添加了该行。mallinfo在看到@OliCharlesworth 的答案后,我也玩了一下输出。

您可以更改 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 

和之间总是有 9 的差,usablep[-2]1之间总是有 9 的差。该方法的优点是它可以准确地告诉您您要求的内容 -指针的大小。其他电话实际上可能会告诉您您真正想要什么...p[-2]uordblksp[-2]

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

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

然后你可以找出任何指针的大小

printf("my pointer size is %ld\n", PSIZE(myPointer));

无需担心指针的类型。我确认这适用于不同类型的指针,以及大于 4G 的块。显然,您可以决定在宏中减去 1,以便该数字与 mallinfo() 完全一致。

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

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

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

于 2013-03-12T17:45:42.690 回答
0

您需要在 malloc 中安装一个钩子来构建一个缓存请求块大小的指针表,然后当您释放时,在以前的 malloc 项目数据库中搜索指针。

这样,您将知道当前分配的堆总和要减少多少(如果这是您的目标),并且将有一个方便的地方列出仍在内存中的堆的所有“区域”。

于 2013-03-12T17:41:27.240 回答