C 疯狂是免费的

C 疯狂是免费的,c,dynamic,malloc,free,structure,C,Dynamic,Malloc,Free,Structure,在我的简单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\

在我的简单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());
}
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());
我得到:

A RSS=980
B RSS=984
C RSS=980
D RSS=980
E RSS=1024
F RSS=1024
D RSS=1024
E RSS=1024
F RSS=1024
我无法解释为什么
C
没有返回
984


如果我运行相同的过程两次,我会得到:

A RSS=980
B RSS=984
C RSS=980
B RSS=984
C RSS=980
看起来不错


但是,在这种情况下:

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());
}
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());

嗯?为什么这里没有释放内存?

内存块已被释放的事实并不一定使该块最适合后续分配。内存管理器有几种选择内存块的策略(最佳匹配、最差匹配、首次匹配)

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


块没有用于满足您的下一个分配请求并不意味着它没有被释放。

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


一般来说,这并不重要。地址空间和虚拟内存通常不被视为稀缺资源。因此,过度努力将其消耗降至最低通常是毫无价值的,而且通常是有害的。

来自
免费()
手册页:“有时候,free实际上可以将内存返回到操作系统,使进程更小。通常,它所能做的就是允许稍后调用malloc以重用空间。同时,空间作为malloc内部使用的自由列表的一部分保留在程序中。”

您不应该将具有副作用的表达式放入
assert
。这是正确的。忽略它。但是,结果仍然令人困惑。请在“strace”下运行程序“因此,您可以监视实际上会对RSS值产生影响的mmap/munmap调用。您可以在代码周围放置一些printf,以便将mmap/munmap与输出中代码的特定点相匹配。如果您多次运行程序,结果是否一致?似乎系统不需要在释放页面上分配的内存后立即交换页面。@vanza:一个很好的建议。对于char*cTemp=malloc(100),我看到mmap2和munmap与传统的malloc;免费(cTemp);。。。对于结构malloc,尽管RSS增加了,但strace没有显示任何mmap或munmap调用!!在产生这个问题的实际程序中,它最终会耗尽内存并崩溃。我的测试表明分配给结构的内存不会被释放。此外,strace并没有显示和malloc关联的mmap2或munmap调用,也并没有显示结构(及其char*)。我仍然很困惑。@MarkRichards:我刚刚在WinDbg中浏览了你的程序(现在手头没有linux机器可玩),用
检查提交的内存!堆
。它很好用。似乎没有任何内存泄漏。请记住,glibc的
malloc
free
不需要调用mmap/munmap,因为已经为CRTs堆保留了未写入的内存。你说的最终内存耗尽并崩溃是什么意思?你能把整个节目都贴出来吗?很有趣。我会在另一个(不同的)盒子上做同样的事情。我修改了程序-删除了第一个工作的malloc。仍然无法调用mmap。请看:在另一个盒子(ubuntu)上测试相同的代码,我看到在结构中释放了一些(而不是全部)分配的内存——基于阅读RSS。在TargetBox上,一个运行debian的arm9处理器,我没有看到任何内存被释放,同样是基于读取RSS。相同的代码。不同的盒子。不同的结果。如果我的程序在运行了几个小时后没有因为缺乏资源而崩溃,我就不会这么执着了。只发生在动态结构中,所以我想知道。。我是否正确地编码了这些内容?RSS不会告诉您内存是否已被释放,因为CRT可以像其他人所说的那样保留该内存以备将来分配。尝试调用glibc的未记录的
malloc_stats()
(从GDB或在调用malloc或free之间插入),或使用valgrind。你发布的代码是正确的,因为你释放了所有你想要的东西。理论上,由于碎片化,某些分配模式可能会导致特定的malloc实现向堆提交越来越多的内存。如果是这种情况,有办法解决,但是你发布的代码不应该有这种情况