delete[] 后 Resident Set Size 保持不变

Resident Set Size remains the same after delete[]

我试图跟踪我的 c++ 项目占用的内存,所以我找到了一个函数,它可以使用来自 this post 的共享内存和私有内存打印 RSS。代码如下

void testMemoryOccupied() {
    int tSize = 0, resident = 0, share = 0;
    ifstream buffer("/proc/self/statm");
    buffer >> tSize >> resident >> share;
    buffer.close();

    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
    double rss = resident * page_size_kb;
    cout << "RSS - " << rss << " kB\n";

    double shared_mem = share * page_size_kb;
    cout << "Shared Memory - " << shared_mem << " kB\n";

    cout << "Private Memory - " << rss - shared_mem << "kB\n";
    cout << endl;
}

我试图测试这是否可行,所以我写道:

    testMemoryOccupied();

    int* foo = new int[10000];
    for (int i=0;i<10000;i++) {
        foo[i] = i;
    }
    testMemoryOccupied();

    int* foo1 = new int[10000];
    for (int i=0;i<10000;i++) {
        foo1[i] = i;
    }
    testMemoryOccupied();

    delete[] foo;
    testMemoryOccupied();

    free(foo1);
    testMemoryOccupied();

结果表明RSS只在这两个for循环后增加,而在delete[]或free()后没有减少。

RSS - 1576 kB
Shared Memory - 1356 kB
Private Memory - 220kB

RSS - 1772 kB
Shared Memory - 1516 kB
Private Memory - 256kB

RSS - 1812 kB
Shared Memory - 1516 kB
Private Memory - 296kB

RSS - 1812 kB
Shared Memory - 1516 kB
Private Memory - 296kB

RSS - 1812 kB
Shared Memory - 1516 kB
Private Memory - 296kB

我知道 "deleting" 只是将一些内存位置标记为 "usable" 但实际上并没有清除它们,这就是为什么 RSS 在这里保持不变的原因吗?

如果是这样,我如何跟踪程序在某个时刻占用的实际内存?

I know "deleting" only marks some memory locations to be "usable" but not actually wiping them out, is that the reason why RSS remains the same here?

是的。 (解除)分配功能的实现通常不会在每次解除分配后尝试向操作系统释放内存,而是保留内存以供进一步分配,以避免获取和释放内存的开销。

通常动态内存的增长与堆栈完全一样,在这种情况下它只会从末尾收缩。在这种情况下,如果驻留集在第一次释放后减少,那将是非常出乎意料的,因为在它之后还有一个现有的后续分配。第二个之后,可能就可以了。

P.S。 GNU C 库有一个函数 malloc_trim 试图从堆中释放内存,还有一个 mallopt 可以用来配置自动修剪的大小阈值等设置。

how could I track the actual memory occupied at some point during the program?

这在某种程度上取决于您所说的 "actual memory occupied" 是什么意思。您是否考虑仍由进程占用的已取消分配的内存?

你可以替换内存分配函数(即malloc)来跟踪每一个分配(注意不要跟踪你需要的数据结构的分配,否则你最终会陷入无限环形)。没有标准的方法来进行这种替换。


您使用从 new[] 获得的指针调用 free。程序的行为未定义。