c++ - 诊断 Mac OS X 上的堆碎片?

标签 c++ c macos memory-management heap-memory

我正在编写的 Core Foundation 应用程序消耗的内存(根据 Activity Monitor 中的“Real Mem”计数)似乎比我实际分配的要多得多。

我已经通过 Instruments 中的 Live Bytes Allocations View 确认我的实际分配是我期望的(大约 10MB),但是 Activity Monitor 中的“Real Mem”计数显示 > 60MB 并且明显在增长。我还使用 Instruments 确认没有泄漏。

我的应用程序保留了一个大的不同大小的缓冲区队列,并且在添加/删除队列项时不断地使用 free()-ing 和 malloc()-ing 缓冲区。

阅读了一些关于堆碎片的内容后,这似乎是对正在发生的事情的可能解释。所以我的问题如下:

  1. 有没有办法在 OS X 上确认这一点,例如也许获得堆的可视化表示?
  2. OS X 是否有像 Windows 一样的可选低碎片堆管理器?

对于任何想要重现该问题的人,以下示例代码很好地显示了相同的症状:

#define MAX_SIZE (10*1024*1024)

int main (int argc, const char * argv[])
{

size_t actual_alloc=0;
size_t max_alloc=0;

char *bigbuf=NULL;
size_t bigsize=0;

for  (long x=0; x<10000000; x++)
{
    if (bigbuf!=NULL)
    {
        actual_alloc -= bigsize;
        free(bigbuf);
    }

    bigsize = rand() % MAX_SIZE; // alloc random amount up to MAX_SIZE
    bigbuf = (char*)malloc(bigsize);
    memset(bigbuf, 'x', bigsize);
    actual_alloc += bigsize;

    if (actual_alloc > max_alloc)
        max_alloc = actual_alloc;

    if (x%100==0)
    {
        printf("alloc = %u \t max = %u\n", 
             (unsigned long)actual_alloc, (unsigned long)max_alloc);

        // max_alloc tends towards 10MB, 
        //  "Real Mem" in activity monitor tends towards 60MB
    }
}


return 0;
}

如果您从上面的代码中删除随机元素,您将按预期获得大约 10MB 的进程内存使用量。

最佳答案

堆是一个复杂的数据结构,你看到的是正常的。仅仅因为您 free() 一个缓冲区并不意味着该库将该内存返回给操作系统。系统调用是有成本的,所以当分配系统请求一 block 内存时,它往往会请求比它需要的更多的内存,这样后续的分配就可以返回内存而无需进入内核。堆还可能为不同的分配大小维护多个分配区域,以避免长时间搜索和碎片化。通过随机分配大小,您已经成功地初始化了其中的几个桶。

您无法预测内存分配子系统或您链接的其他系统库的行为,因此 Activity Monitor 或 top 或任何其他工具不会为您提供有意义的信息。如果您想跟踪内存分配或泄漏,请使用 malloc 调试器或类似 valgrind 的工具。

关于c++ - 诊断 Mac OS X 上的堆碎片?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9203677/

相关文章:

c++ - 欧拉计划 #31 蛮力

c++ - 是否可以用 C++17 中的 std::any 比较两个任意函数?

c - 如何使用 read() 存储单词?

macos - NSView 子类中未调用 cancelOperation

macos - 通过 cmake 为 mac 编译通用库时包括 i386 和 x86_64 的不同 header

xcode - NSTextView 自动完成和标签转换

.net - 将 char* 传递给 .Net 的最佳方式

c# - PInvoke x64 崩溃与 .Net 4.0

c - 如何在 C 中拉出 argv 位置 1 中的字符串

c++ - 同时替换多个字符