c/c++语言开发共享为什么mstats和malloc_zone_statistics在免费后没有显示恢复的内存?

我正在尝试编写一些unit testing来检查内存是否已被释放 – 以检查内存泄漏 – 在OS X(10.9 Mavericks)上。 我正在尝试使用mstats()和malloc_zone_statistics()来发现我需要的信息。 但似乎他们没有显示内存被释放(参见下面的示例输出…在调用free()后内存使用率不会改变)

我怀疑这与堆管理有关,而不是与这些函数的问题有关。 我认为堆不释放释放的内存,也许它可以重用它而不需要删除和添加块的开销。

更新:找到的解决方案……在底部提供……

这是我的测试程序的输出:

=== Initial conditions === in use: 23584, allocated: 9437184, blocks: 320 SimpleLeaker(19583,0x7fff7b2a2310) malloc: total: 9437184, used: 23584, free: 9413600 === Before allocation === in use: 23584, allocated: 9437184, blocks: 320 SimpleLeaker(19583,0x7fff7b2a2310) malloc: total: 9437184, used: 23584, free: 9413600 === After malloc === in use: 33824, allocated: 9437184, blocks: 321 SimpleLeaker(19583,0x7fff7b2a2310) malloc: total: 9437184, used: 33824, free: 9403360 === After free === in use: 33824, allocated: 9437184, blocks: 321 SimpleLeaker(19583,0x7fff7b2a2310) malloc: total: 9437184, used: 33824, free: 9403360 

以下是该程序的C代码:

  #include  #include  #include  #include  #include  #include  #include  #include  /** heapStats() * print the output from the mstats() function: total heap bytes, * used bytes, and free bytes. */ void heapStats() { struct mstats ms = mstats(); malloc_printf( "total: %d, used: %d, free: %dn", ms.bytes_total, ms.bytes_used, ms.bytes_free); } /* heapInUse() * Gather the heap usage metrics from each zone, using * malloc_zone_statistics(). */ void heapInUse( size_t * bytesInUse, size_t * blocksInUse, size_t * sizeAllocated) { *bytesInUse = 0; *blocksInUse = 0; *sizeAllocated = 0; unsigned int i; vm_address_t * zones; unsigned int count; kern_return_t rc = malloc_get_all_zones(mach_task_self(), 0, &zones, &count); if (0 != rc) { fprintf(stderr, "rc was %dn", rc); } for (i = 0; i < count; ++i) { malloc_zone_t * zone = (malloc_zone_t*)zones[i]; char const * name = malloc_get_zone_name(zone); if (NULL == name) { continue; } malloc_statistics_t stats; stats.blocks_in_use = 0; stats.size_in_use = 0; stats.max_size_in_use = 0; stats.size_allocated = 0; malloc_zone_statistics(zone, &stats); *bytesInUse += stats.size_in_use; *blocksInUse += stats.blocks_in_use; *sizeAllocated += stats.size_allocated; } } /** main() * entry point */ int main(int argc, const char * argv[]) { char * buff = (char *)0; size_t bytesInUse = 0; size_t blocksInUse = 0; size_t sizeAllocated = 0; printf("=== Initial conditions ===n"); heapInUse(&bytesInUse, &blocksInUse, &sizeAllocated); printf( "in use: %zu, allocated: %zu, blocks: %zun", bytesInUse, sizeAllocated, blocksInUse); heapStats(); printf("=== Before allocation ===n"); heapInUse(&bytesInUse, &blocksInUse, &sizeAllocated); printf( "in use: %zu, allocated: %zu, blocks: %zun", bytesInUse, sizeAllocated, blocksInUse); heapStats(); // Allocate the buffer // buff = (char *)malloc(10000); printf("=== After malloc ===n"); heapInUse(&bytesInUse, &blocksInUse, &sizeAllocated); printf( "in use: %zu, allocated: %zu, blocks: %zun", bytesInUse, sizeAllocated, blocksInUse); heapStats(); // Free the buffer // if (NULL != buff) { free(buff); buff = NULL; } printf("=== After free ===n"); heapInUse(&bytesInUse, &blocksInUse, &sizeAllocated); printf( "in use: %zu, allocated: %zu, blocks: %zun", bytesInUse, sizeAllocated, blocksInUse); heapStats(); // Get out // return 0; } 

解决方案:感谢John Zwinck的回复,我仔细研究了malloc/malloc.h ,发现了一个方法malloc_zone_pressure_relief() ,我可以使用它来强制堆释放未使用的字节,以便我可以获得准确的指标。

所以我添加了这个方法:

 void freeAsMuchAsPossible() { vm_address_t * zones; unsigned int count; unsigned int i; kern_return_t rc = malloc_get_all_zones(mach_task_self(), 0, &zones, &count); if (0 != rc) { fprintf(stderr, "rc was %dn", rc); } for (i = 0; i < count; ++i) { malloc_zone_t * zone = (malloc_zone_t*)zones[i]; char const * name = malloc_get_zone_name(zone); if (NULL == name) { continue; } malloc_zone_pressure_relief(zone, 0); } } 

并在每次调用heapInUse()之前调用它,如下所示:

 printf("=== Before allocation ===n"); freeAsMuchAsPossible(); heapInUse(&bytesInUse, &blocksInUse, &sizeAllocated); printf( "in use: %zu, allocated: %zu, blocks: %zun", bytesInUse, sizeAllocated, blocksInUse); heapStats(); 

现在我得到预期和有用的结果,例如:

 === Initial conditions === in use: 23584, allocated: 9437184, blocks: 4294966976 SimpleLeaker(22142,0x7fff7b2a2310) malloc: total: 9437184, used: 23584, free: 9413600 === Before allocation === in use: 23584, allocated: 9437184, blocks: 4294966976 SimpleLeaker(22142,0x7fff7b2a2310) malloc: total: 9437184, used: 23584, free: 9413600 === After malloc === in use: 33824, allocated: 9437184, blocks: 4294966967 SimpleLeaker(22142,0x7fff7b2a2310) malloc: total: 9437184, used: 33824, free: 9403360 === After free === in use: 23584, allocated: 9437184, blocks: 4294966966 SimpleLeaker(22142,0x7fff7b2a2310) malloc: total: 9437184, used: 23584, free: 9413600 

使用这种技术,我可以编写检查内存泄漏的unit testing。 非常好。

    在OS X上,从10.7开始,我们可以使用malloc_zone_pressure_relief()来强制堆释放未使用的字节。 我用解决方案更新了我的问题。

    感谢John Zwinck的反应让我再次密切关注malloc.h,在那里我发现了这种方法。

    你可能是对的:每次调用free()时,分配器都不会将内存释放回操作系统。 但您可以使用mallopt()更改此设置 。 尝试将M_MMAP_THRESHOLD设置为0.这将使每个单独的分配独立。 您可能不希望将其用于生产,但是对于测试它可能对您有所帮助。

    我建议查看OSX leaks工具以查找程序中的内存泄漏。 可在此处找到介绍性文章: Mac Developer Library中的泄漏文档 。 你可以做man leaks了解更多细节。 另外,仅针对您的问题1,您可以使用libgmalloc 。 请man libgmalloc了解更多。 此外,这些手册页包含指向malloc_history等其他工具的链接,您可能会发现这些工具对您的目的有用和/或更快。

      以上就是c/c++开发分享为什么mstats和malloc_zone_statistics在免费后没有显示恢复的内存?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/562484.html

      (0)
      上一篇 2021年2月4日
      下一篇 2021年2月4日

      精彩推荐