2011-09-22 32 views
5

在我简单的C程序(gnu linux)中,我得到了proc/stat的rss值。
int GetRSS()从我的过程返回proc/stat的RSS值。疯狂是免费的()


在这种情况下:

printf("A RSS=%i\n", GetRSS()); 
char *cStr = null; 
cStr = malloc(999999); 
if (cStr != NULL) 
{ 
    printf("B RSS=%i\n", GetRSS()); 
    free(cStr); 
    printf("C RSS=%i\n", GetRSS()); 
} 

我得到:

A RSS=980 
B RSS=984 
C RSS=980 

我无法解释为什么C没有返回984


如果我运行同样的程序我两次获得:

A RSS=980 
B RSS=984 
C RSS=980 
B RSS=984 
C RSS=980 

看起来不错。


但是,在这种情况下:

struct _test 
{ 
    char *pChar; 
} 
struct _test **test_ptr; 

int i = 0; 
printf("D RSS=%i\n",GetRSS()); 
assert(test_ptr = (struct _test **)malloc((10000) * sizeof(struct _test *))); 

for (i = 0; i < 1000; i++) 
{ 
    assert(test_ptr[i] = (struct _test *)malloc(sizeof(struct _test))); 
    test_ptr[i]->pChar=strdup("Some garbage"); 
} 

printf("E RSS=%i\n", GetRSS()); 

for (i=0; i<1000; i++) 
{ 
    free(test_ptr[i]->pChar); 
    free(test_ptr[i]); 
} 

free(test_ptr); 
printf("F RSS=%i\n", GetRSS()); 

我得到:

D RSS=980 
E RSS=1024 
F RSS=1024 
D RSS=1024 
E RSS=1024 
F RSS=1024 

咦?为什么记忆不在这里释放?

+9

您不应该将带有副作用的表达式放入'assert'中。 –

+0

确实够了。忽略它。但结果却令人困惑。 –

+1

在“strace”下运行您的程序,以便您可以监视实际上会对RSS值产生影响的mmap/munmap调用。您可以在代码中放置一些printfs,以便您可以将mmap/munmap与输出中代码的特定点进行匹配。 – vanza

回答

5

一块内存已被释放的事实而不是必然使该块最适合后续分配。内存管理器有几种选择内存块的策略(最佳拟合,最差拟合,首次拟合)。

大多数内存管理器也会尝试合并空闲块,但有些尝试在合并之前尽可能长时间让空闲块“老化”,理论上说,随着它们的老化,它们旁边的块会有更好的机会也可以被释放,提高合并块的成功率(从而减少碎片化)。

该块未用于满足您的下一个分配请求的事实而不是表示它没有被释放。

1

您的malloc库选择不这样做。这可能是出于战略原因(避免以后必须去系统获得更多内存),或者可能是由于限制(在该特定原因下,它不认识到它可以释放内存)。

一般来说,没关系。地址空间和虚拟内存通常不被视为稀缺资源。因此,尽量减少消费量通常是毫无价值的,而且往往是有害的。

2

free()手册页:“偶尔,free可以实际将内存返回给操作系统,并且使进程变得更小。通常情况下,只需稍后再调用malloc即可重用该空间。同时,该空间作为malloc内部使用的自由列表的一部分保留在程序中。“

+0

在产生这个问题的真正程序的情况下,它最终会耗尽内存并崩溃。我的测试表明分配给该结构的内存不会被释放。此外,strace不会显示与malloc相关的mmap2或munmap调用,也不会显示结构(及其char *)。我仍然难倒。 –

+0

@MarkRichards:我刚刚在WinDbg中介绍了您的程序(现在没有可用的Linux机器),用'!heap'检查提交的内存。它工作正常。似乎没有任何内存泄漏。请记住,glibc的'malloc'和'free'不需要调用mmap/munmap,因为已经为CRT堆保留了未编译的内存。你什么意思最终耗尽内存和崩溃?你也许可以将你的整个程序贴上去? –

+0

非常有趣。我会在另一个(不同的)盒子上做同样的事情。我修改了程序 - 删除了第一个工作的malloc。仍然无法调用mmap。请参阅:http://pastebin.com/m3gAJBhs –