2013-03-12 37 views
2

我想跟踪一个大型应用程序当前分配了多少内存。有没有办法知道在Linux中传递给__free_hook的指针的大小?

我发现我可以安装周围的malloc /免费/ realloc的挂钩,以拦截内存分配来电:

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

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

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

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

有没有什么办法(即使它是一个黑客)在免费调用时使用Linux(64位)大小的ptr(使用默认的g ++ malloc)?

+0

可能重复[是否有可能找到分配给指针的内存,而不搜索malloc语句](http://stackoverflow.com/questions/5813078/is-it-possible-to-find-the -memory-allocated-to-the-pointer-without-searching-fo) – Floris 2013-03-13 13:19:47

+0

问题是类似的,但不完全相同。那个人打算用它来计算一个数组在代码本身中有多久,这个答案中建议避免使用这个数组。在这种情况下,这个问题只是为了跟踪总内存。 – 2013-03-13 16:21:46

+0

也许 - 但接受的答案在两种情况下都是一样的......“使用malloc_usable_size()”。这使得它至少在我心中是一个“可能的重复”。通过创建链接,我们为遇到一个问题的人提供了看到更多可能答案的机会。 – Floris 2013-03-13 16:32:56

回答

5

Linux手册malloc_usable_size

malloc_usable_size()返回的字节在 动态分配缓冲器的ptr可用的数目,这可以比 请求的大小的情况下(但保证是至少一样大,如果 请求成功)。通常,您应该存储 请求的分配大小,而不是使用此功能。

3

这不是直接回答你的问题,但看到你有兴趣在总分配的内存,然后在这里是解决方案:

我想你会对它返回的结构的uordblks字段感兴趣。

注意,这不是一个标准的POSIX功能,但我想这是你所期望的非标准反省这样的...

+0

当你超过4 GB时,mallinfo不起作用 – 2013-03-12 18:19:17

+0

@JeroenDirks:嗯,这是一个公平点! – 2013-03-12 18:28:46

0

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

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

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 

总会有9 usablep[-2]1之间p[-2]uordblks之间,以及不同。 p[-2]方法的优点在于它可以准确地告诉你你的询问 - 这个指针的大小。其他通话可能实际上告诉你什么你真想 ...

PS这很可能是对的内存非常大的块,你需要看的是住在*((long int*)(p)-1)long integer。这给了我灵感的一个不错的宏:

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

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

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

而不必担心指针的类型。我确认这适用于不同类型的指针,对于块> 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*)) 

链接的答案强烈建议只用这个调试,而不是依赖于它的实际代码。我感到不得不重复这个警告。

+0

这很大程度上取决于glibc的malloc du jour如何做事......最好跟@fanl的答案。 – vonbrand 2013-03-12 20:28:53

相关问题