D/Tango 中的 malloc 和 free 不释放内存?

发布于 2024-07-30 18:08:25 字数 1476 浏览 11 评论 0原文

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

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

here is a simple d/tango code in windows:

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);


}

when I run the program, memory stays low ~2MB, and when I allocate an array of 100MB to the pointer memory usage jumps to ~100MB, which is fine. However, after free memory is still (I'm looking at task manager) at 100MB to the end of the program.

I thought it might be to windows pagefile cache or something, so I've tried a simple C++ program:

#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;
}

I've compiled it with g++ and everything seems to work like it should. When program starts - memory usage ~900kb, after allocation ~100MB, after free ~1,2MB...

So, what am I doing wrong or is this a bug?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

星軌x 2024-08-06 18:08:25

这将取决于免费的实现方式。 如需一些有趣的阅读内容,请查看 Doug Lea 的分配器,它尝试能够有效管理各种大小的内存请求。 他主要关心的是 mallocfree 调用是否快速且正确。

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

It is going to depend on how free is implemented. For some interesting reading, take a look at Doug Lea's allocator, which tries to be efficient at managing memory requests that can span a wide range of sizes. His primary concern is that the malloc and free calls be fast, and correct.

But he does mention the issue of returning memory to the OS, and discusses what hinders it (memory fragmentation) and what aids it (use of mmap, or in a less flexible manner, sbrk). Once you've read this article, you'll have a clearer idea of the trade-offs which lead to infrequent return of memory to the OS.

我早已燃尽 2024-08-06 18:08:25

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

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

When you free memory with "free", it's likely that it doesn't actually free the memory.

It could be that it is simply marking it as free but holding on to it in case you request more memory later. If for some reason the system starts running low on memory, the runtime might actually free it at that point.

眼眸里的那抹悲凉 2024-08-06 18:08:25

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

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

It just means that Digital Mars' implementation of malloc and free doesn't return memory to the OS, even when you allocate a huge chunk like that. You could try using malloc and free from msvcrt.dll instead, maybe they'll free the memory.

Or you can use the Windows API directly, if this problem only exists for DMD on Windows. The easiest is to use the HeapAlloc and HeapFree functions, but I don't know if they'll do what you want either. A sure way is the more low-level VirtualAlloc and VirtualFree, which allocate directly from the OS instead of creating a heap first. Those are also the functions that HeapAlloc, malloc, new in C++, etc, ultimately use when they request memory from the OS.

九公里浅绿 2024-08-06 18:08:25

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

你确定你测量得对吗?

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

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

This is strange. From looking at the Tango source, malloc/free in tango.stdc.stdlib are just the C standard library functions, so there should rightfully be no difference - and in fact, when I try it using Phobos and std.c.stdlib under Linux, the memory goes right back down as it should.

Are you sure you're measuring it right?

PS: You can just do armageddon[0 .. total_n] = 5;

PS2: I tried your Tango code under Linux, and it goes back down as expected. Looks like a Windows issue.

筱武穆 2024-08-06 18:08:25

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

You can start by looking at _heapmin(). free() does not return unused heap to the OS, it it only marks it as free and coalesces with nearest free neighbors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文