3

这是 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 ...

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

4

5 回答 5

3

这将取决于如何实现免费。对于一些有趣的阅读,看看Doug Lea 的分配器,它试图有效地管理可以跨越各种大小的内存请求。他主要关心的是mallocfree调用是否快速且正确。

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

于 2009-08-14T18:30:45.540 回答
2

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

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

于 2009-08-14T17:47:29.200 回答
2

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

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

于 2009-08-14T20:01:54.017 回答
1

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

你确定你测量对了吗?

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

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

于 2009-08-14T18:53:19.177 回答
0

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

于 2009-08-14T18:05:18.680 回答