这是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 pagefile缓存或其他东西,所以我尝试了一个简单的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 ......
那么,我做错了什么或这是一个错误?
答案 0 :(得分:3)
这将取决于免费的实施方式。对于一些有趣的阅读,请查看Doug Lea's allocator,它试图有效地管理可以跨越各种大小的内存请求。他主要担心的是 malloc 和免费调用是否快速且正确。
但他确实提到了将内存返回给操作系统的问题,并讨论了阻碍它的内容(内存碎片)及其帮助(使用 mmap ,或者一种不太灵活的方式, sbrk )。一旦你阅读了这篇文章,你就会更清楚地了解导致不经常将内存返回给操作系统的权衡。
答案 1 :(得分:2)
当你用“免费”释放内存时,它可能实际上没有释放内存。
可能是它只是将其标记为免费,但如果您稍后请求更多内存,则可以保留它。如果由于某种原因系统内存开始运行不足,那么运行时可能会在那时释放它。
答案 2 :(得分:2)
这只是意味着Digital Mars对malloc和free的实现不会将内存返回给操作系统,即使你分配了大量的内存。您可以尝试使用malloc并免费使用msvcrt.dll,也许他们会释放内存。
或者,如果此问题仅存在于Windows上的DMD,则可以直接使用Windows API。最简单的方法是使用HeapAlloc和HeapFree函数,但我不知道它们是否也能做你想做的事情。一种可靠的方法是更低级别的VirtualAlloc和VirtualFree,它们直接从操作系统分配,而不是先创建堆。这些也是HeapAlloc,malloc,C ++等新功能,当它们从操作系统请求内存时最终使用的功能。
答案 3 :(得分:1)
这很奇怪。从Tango源看,tango.stdc.stdlib中的malloc / free只是C标准库函数,所以应该没有区别 - 实际上,当我在Linux下使用Phobos和std.c.stdlib进行尝试时,记忆会正确地回落。
你确定你正在测量它吗?
PS:你可以做一次世界末日[0 .. total_n] = 5;
PS2:我在Linux下尝试了你的Tango代码,它按预期的那样回落了。看起来像Windows问题。
答案 4 :(得分:0)
您可以先查看_heapmin()。 free()不会将未使用的堆返回给操作系统,它只会将其标记为空闲并与最近的自由邻居合并。