【问题标题】:malloc and free in D/Tango not freeing memory?D/Tango 中的 malloc 和 free 不释放内存?
【发布时间】:2009-08-14 17:38:10
【问题描述】:

这是一个简单的 windows d/tango 代码:

module d_test.d;

import tango.util.log.Trace;
import tango.core.Thread;
import tango.stdc.stdlib : malloc, free;

void main() {

    Trace.formatln("Checking in...");
    Thread.sleep(10);

    int total_n = (100 * 1000 * 1000) / int.sizeof; // fill mem with 100MB of ints
    int* armageddon = cast(int*)malloc(total_n * int.sizeof);

    for(int i = 0; i < total_n; ++i) {
        armageddon[i] = 5;
    }

    Trace.formatln("Checking in...");
    Thread.sleep(10);

    free(armageddon);
    armageddon = null;

    Trace.formatln("Checking in...");
    Thread.sleep(10);


}

当我运行程序时,内存保持低~2MB,当我为指针分配一个 100MB 的数组时,内存使用量跳到~100MB,这很好。但是,在程序结束后,可用内存仍然(我正在查看任务管理器)为 100MB。

我认为可能是windows页面文件缓存什么的,所以我尝试了一个简单的C++程序:

#include <iostream>
#include <windows.h>

using namespace std;

int main() {

  Cout << "Checking in..." <<< endl;
  Sleep(10000);


  int total_n = (100 * 1000 * 1000) / sizeof(int);
  int* armageddon = (int*)malloc(total_n * sizeof(int));

  for(int i = 0; i < total_n; ++i) {
    armageddon[i] = 5;
  }

  Cout << "Checking in..." <<< endl;
  Sleep(10000);

  free(armageddon);
  armageddon = NULL;

  Cout << "Checking in..." <<< endl;
  Sleep(10000);


return 0;
}

我已经用 g++ 编译了它,一切似乎都正常工作。程序启动时 - 内存使用 ~900kb,分配后 ~100MB,释放后 ~1,2MB...

那么,我做错了什么还是这是一个错误?

【问题讨论】:

  • malloc 和 free 只是 C 调用的说唱歌手。我不知道为什么结果会不同。
  • 哟哟! // 我的名字是 malloc,我是一个糟糕的说唱歌手。 // 把你所有的记忆都给我,我会把它扔进垃圾箱里

标签: memory d tango


【解决方案1】:

这将取决于 free 的实现方式。对于一些有趣的阅读,请查看Doug Lea's allocator,它试图有效地管理可以跨越各种大小的内存请求。他主要关心的是 mallocfree 调用是否快速且正确。

但他确实提到了将内存返回给操作系统的问题,并讨论了阻碍它(内存碎片)和帮助它(使用mmap,或在一种不太灵活的方式,sbrk)。阅读本文后,您将更清楚地了解导致内存不经常返回操作系统的权衡取舍。

【讨论】:

    【解决方案2】:

    当您使用“free”释放内存时,它可能实际上并没有释放内存。

    这可能是它只是将其标记为空闲,但会保留它以防您稍后请求更多内存。如果由于某种原因系统开始内存不足,运行时实际上可能会在此时释放它。

    【讨论】:

    • 好吧,如果那是真的——那你知道用武力释放它的方法吗?
    • 为什么需要它返回操作系统?只要您有交换空间,拥有未使用的数据空间的成本几乎为零。
    • @BCS 我正在监视我的程序进程内存使用情况以进行分析,因为我想在需要时限制使用的内存总量。而且我也很好奇为什么它会像它一样有效,我怎样才能按照我想要的方式去做。
    • @Keyframe 你想监控 malloc 的内存而不是 GC 分配的内存?由于 GC 有统计信息......(我知道有些用例需要避免 GC。)
    • @larsivi 确实,我计划在我正在开发的游戏中很少使用 GC 内存,如果有的话。而且我有一个系统可以跟踪内存使用情况并对其进行限制。
    【解决方案3】:

    这只是意味着 Digital Mars 的 malloc 和 free 实现不会将内存返回给操作系统,即使您分配了这样一个大块。您可以尝试使用 malloc 并从 msvcrt.dll 中释放,也许它们会释放内存。

    如果此问题仅存在于 Windows 上的 DMD,您也可以直接使用 Windows API。最简单的是使用 HeapAlloc 和 HeapFree 函数,但我不知道它们是否会做你想做的事。一个可靠的方法是更底层的 VirtualAlloc 和 VirtualFree,它们直接从操作系统分配,而不是先创建堆。这些也是 HeapAlloc、malloc、C++ 中的 new 等在向操作系统请求内存时最终使用的函数。

    【讨论】:

    • 检查您是否可以尝试使用 DMC(数字 mars C++ 编译器)作为 IIRC 的 C++ 程序,它使用与 D 相同的 malloc。
    【解决方案4】:

    这很奇怪。从 Tango 源代码来看,tango.stdc.stdlib 中的 malloc/free 只是 C 标准库函数,所以应该没有区别 - 事实上,当我在 Linux 下使用 Phobos 和 std.c.stdlib 尝试它时,内存会按原样返回。

    你确定你测量对了吗?

    PS:你可以只做世界末日[0 .. total_n] = 5;

    PS2:我在 Linux 下尝试了您的 Tango 代码,它按预期返回。看起来像是 Windows 问题。

    【讨论】:

      【解决方案5】:

      您可以从查看 _heapmin() 开始。 free() 不会将未使用的堆返回给操作系统,它只会将其标记为空闲并与最近的空闲邻居合并。

      【讨论】:

        猜你喜欢
        • 2012-05-15
        • 2014-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-28
        • 1970-01-01
        • 2014-11-28
        • 1970-01-01
        相关资源
        最近更新 更多