UNIX 与 Windows 内存释放

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/236001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:31:22  来源:igfitidea点击:

UNIX vs Windows memory deallocation

windowslanguage-agnosticunixmemory-management

提问by Jason Baker

My understanding is that in unix, when memory is freed, the memory doesn't get returned back to the operating system, it stays in the process to be used again for the next call to malloc.

我的理解是,在 unix 中,当内存被释放时,内存不会返回给操作系统,它会停留在进程中,以便下次调用 malloc 时再次使用。

On windows, I understand that the memory actually gets returned to the operating system.

在 Windows 上,我知道内存实际上会返回给操作系统。

Is there any big difference between these two ways of doing things or are they just two different ways of doing the same thing? And if there are any pros/cons to these two methods, what are they?

这两种做事方式之间有什么大的区别,或者它们只是做同一件事的两种不同方式?如果这两种方法有任何优点/缺点,它们是什么?

EDIT:Thanks for the clarification. I had always thought this was an OS thing (since processes never seem to decrease in size in UNIX-like systems, but do in windows).

编辑:感谢您的澄清。我一直认为这是操作系统的事情(因为进程在类 UNIX 系统中似乎永远不会减小,但在 Windows 中会减小)。

回答by CesarB

There isn't much difference between Windows and Unix with respect to that.

Windows 和 Unix 在这方面没有太大区别。

In both, there are two levels of allocation. The operating system allocates memory to the process in large chunks (one page or more; on x86, the page size is usually 4096 bytes). The runtime libraries, running within the process, subdivide this space and allocate parts of it to your code.

两者都有两个级别的分配。操作系统以大块(一页或更多页;在 x86 上,页大小通常为 4096 字节)为进程分配内存。在进程内运行的运行时库细分此空间并将其中的一部分分配给您的代码。

To return the memory to the operating system, first all the memory allocated from one of these large chunks has to be released to the runtime library. The runtime library then can, if it wants, tell the operating system to release that chunk of memory.

要将内存返回给操作系统,首先必须将从这些大块之一分配的所有内存释放到运行时库。然后,如果需要,运行时库可以告诉操作系统释放该内存块。

On Linux, you have brkand mmap. brkcontrols the size of of a large chunk of memory allocated to your process; you can expand or shrink it, but only at one end. malloctraditionally expands this chunk of memory when it needs more memory to allocate from, and shrinks it when possible. However, shrinking is not easy; it takes a single one-byte ill-timed allocation at the end to make it unable to shrink even if everything before that allocation has been freed. This is the source of the "Unix doesn't release memory back" meme.

在 Linux 上,您有brkmmap. brk控制分配给进程的大块内存的大小;你可以扩大或缩小它,但只能在一端。malloc传统上,当需要分配更多内存时扩展这块内存,并在可能时缩小它。然而,缩小并不容易;最后需要一个单字节的不合时宜的分配,以使其无法缩小,即使该分配之前的所有内容都已被释放。这是“Unix 不释放内存”模因的来源。

However, there's also anonymous mmap. Anonymous mmaprequests a chunk of memory from the operating system, which can be placed anywhere in the process memory space. This chunk can be returned easily when it's not needed anymore, even if there are later allocations which weren't released yet. mallocuses also mmap(particularly for large allocations, where a whole chunk of memory can be easily returned after being freed).

但是,也有匿名的mmap。Anonymousmmap向操作系统请求一块内存,它可以放置在进程内存空间的任何位置。当不再需要这个块时,它可以很容易地返回,即使有尚未释放的后续分配。malloc也使用mmap(特别是对于大分配,在释放后可以轻松返回整个内存块)。

Of course, on both Windows and Linux if you do not like the behavior of the memory allocator (or allocators) from the runtime libraries, you can use your own, asking memory from the operating system and subdividing it the way you want (or sometimes asking memory from another allocator, but in larger blocks). One interesting use is to have an allocator for all the memory associated with a task (for instance, a web server request), which is completely discarded at the end of the task (with no need to free all the pieces individually); another interesting use is an allocator for fixed-size objects (for instance, five-byte objects), which avoids memory fragmentation.

当然,在 Windows 和 Linux 上,如果您不喜欢来自运行时库的内存分配器(或多个分配器)的行为,您可以使用自己的,从操作系统请求内存并按照您想要的方式细分它(或者有时从另一个分配器请求内存,但在更大的块中)。一个有趣的用途是为与任务(例如,Web 服务器请求)相关联的所有内存分配一个分配器,在任务结束时将其完全丢弃(无需单独释放所有部分);另一个有趣的用途是固定大小对象(例如,五字节对象)的分配器,它可以避免内存碎片。

回答by DavidK

Note that I know much more about Windows than Unix in what follows ...

请注意,在以下内容中,我对 Windows 的了解比 Unix 多得多……

What actually happens with memory allocation and deallocation isn't quite what you describe, in any case. This is because there's two very different concepts at work here: the physical memory that the computer possesses, and the virtual address space of the program, the memory that your program thinks it can use.

无论如何,内存分配和释放实际发生的情况与您所描述的并不完全相同。这是因为这里有两个非常不同的概念在起作用:计算机拥有的物理内存,以及程序的虚拟地址空间,即程序认为可以使用的内存。

When your program requests more memory from the operating system, what is really happening is that previously unavailable virtual address space in your program is being set up as accessible by the program. Modern operating systems don't work by just having a pool of "real" (that is, physical) memory that it hands out to processes when they make an allocation request: it maintains the virtual address space for every running program, and, when programs actually access parts of that virtual address space, ensures that this is mapped to some physical memory, possibly by swapping out some part of another program's address space to the swap file on disk.

当您的程序从操作系统请求更多内存时,真正发生的是程序中以前不可用的虚拟地址空间被设置为可由程序访问。现代操作系统的工作不仅仅是拥有一个“真实”(即物理)内存池,当进程发出分配请求时,它会分发给进程:它为每个正在运行的程序维护虚拟地址空间,并且,当程序实际上访问该虚拟地址空间的一部分,确保它被映射到一些物理内存,可能通过将另一个程序的地址空间的一部分交换到磁盘上的交换文件。

As an example of this, on Windows each thread starts with (by default) a megabyte of stack space allocated for it. This doesn't mean that every thread consumes a megabyte of the machine's physical memory: it is simply that the address space is set up so that it is available for use. In this sense it doesn't really work to think about the operating system giving your program memory and then the program giving it back - it just doesn't work like that.

例如,在 Windows 上,每个线程都以(默认情况下)为其分配的 1 兆字节堆栈空间开始。这并不意味着每个线程都消耗机器物理内存的 1 兆字节:只是设置了地址空间以供使用。从这个意义上说,考虑操作系统为您的程序提供内存然后程序将其返回并没有真正起作用 - 它只是不能那样工作。

回答by anjanb

It all depends on which C runtime library you use. There is NO specific UNIX way or WINDOWS way. Each compiler vendor(HP, SUN, MS, GNU) ships with their own runtime library that contains the logic for malloc. each implementation of malloc will operate same/different depending on the OS. Neither UNIX/LINUX/Windows needs that a free "ACTUALLY RETURN" the memory back to the OS. That would be too expensive (since your alloc() would be in very small chunks)

这完全取决于您使用的 C 运行时库。没有特定的 UNIX 方式或 WINDOWS 方式。每个编译器供应商(HP、SUN、MS、GNU)都带有自己的运行时库,其中包含 malloc 的逻辑。malloc 的每个实现将根据操作系统运行相同/不同。UNIX/LINUX/Windows 都不需要将内存“实际返回”给操作系统。那太贵了(因为你的 alloc() 将是非常小的块)

Recently mozilla Firefox borrowed a malloc() implementation from *BSD OS. They chose to use a different malloc than what their compiler vendor (multiple in this case -- gcc and VC++) shipped. Since they wanted a certain behavior, they got what they wanted.

最近 mozilla Firefox 从 *BSD OS 借用了 malloc() 实现。他们选择使用与其编译器供应商(在本例中为多个——gcc 和 VC++)所提供的不同的 malloc。因为他们想要某种行为,所以他们得到了他们想要的。

回答by Hugh Allen

The only operating system where you can't easily give allocated memory back to the system is OS X - quoting Firefox 3 Memory Usage:

唯一无法轻松将分配的内存归还给系统的操作系统是 OS X - 引用Firefox 3 Memory Usage

After extensive testing and confirmation from Apple employees we realized that there was no way for an allocator to give unused pages of memory back while keeping the address range reserved.. (You can unmap them and remap them, but that causes some race conditions and isn't as performant.) There are APIs that claim to do it (both madvise() and msync()) but they don't actually do anything.

经过 Apple 员工的大量测试和确认后,我们意识到分配器无法在保留地址范围的同时返回未使用的内存页。(您可以取消映射并重新映射它们,但这会导致一些竞争条件,并且性能不高。)有一些 API 声称可以做到这一点(madvise() 和 msync()),但它们实际上并没有做任何事情。

回答by David Cournapeau

As other mentioned, this is more linked to the malloc implementation than the OS per se. On linux, with glibc, the memory is actually always returned to the OS above a certain size: glibc malloc uses mmap for big allocations (controlled by MMAP_THRESHOLD), and in that case, free calls munmap, which frees automatically the reserved memory. Below that threshold, it uses brk, and free does not "return" the memory in that case.

正如其他人所提到的,这比操作系统本身更多地与 malloc 实现相关联。在 linux 上,使用 glibc,内存实际上总是在一定大小以上返回给操作系统:glibc malloc 使用 mmap 进行大分配(由 MMAP_THRESHOLD 控制),在这种情况下,free 调用 munmap,它会自动释放保留的内存。低于该阈值,它使用 brk,并且在这种情况下 free 不会“返回”内存。

Note that the above explanation is not exact: to be precise, you need to know the difference between physical memory, virtual memory, etc... This is well explained here:

注意上面的解释并不准确:准确的说,你需要知道物理内存、虚拟内存等的区别……这里很好解释:

http://blogs.msdn.com/oldnewthing/archive/2004/08/22/218527.aspx

http://blogs.msdn.com/oldnewthing/archive/2004/08/22/218527.aspx

回答by VonC

From this Memory Managementarticle

来自这篇内存管理文章

Malloc does not normally return the freed memory to the operating system; it remains owned by the process until it terminates. The process can reuse it the next time it requests more memory, but other programs will not have access to it, even if no other memory is available. As a corollary, then, the memory footprint of a program is the size of the largest allocation(s) made at any one time. Thus it is always wise to free objects you do not need, especially large ones as soon as possible, to minimize this footprint.

Malloc 通常不会将释放的内存返回给操作系统;它一直归进程所有,直到它终止。进程可以在下次请求更多内存时重用它,但其他程序将无法访问它,即使没有其他内存可用。因此,作为一个推论,程序的内存占用是在任何时候进行的最大分配的大小。因此,尽快释放不需要的对象总是明智的,尤其是大的对象,以尽量减少这种占用空间。

That article does suggest that in Windows, at least for C program, the memory is not returned to the OS.

那篇文章确实建议在 Windows 中,至少对于 C 程序,内存不会返回给操作系统。

So I am not sure about your generalization about windows memory deallocation.

所以我不确定你对 Windows 内存释放的概括。

That said, you can try and Emulating UNIX Memory Management Under Microsoft Windows, by implementing low level system calls sbrk and mmap/munmap on Windows.

也就是说,您可以通过在 Windows 上实现低级系统调用 sbrk 和 mmap/munmap来尝试在 Microsoft Windows 下模拟 UNIX 内存管理

回答by paxdiablo

I don't know about Windows but, on UNIX, the brk()call is used to bring more memory into the address space for use by the malloc()calls.

我不了解 Windows,但在 UNIX 上,brk()调用用于将更多内存带入地址空间以供malloc()调用使用。

I've never seen this memory returned to the OS until the process terminates. You can usually see this with tools such as top.

在进程终止之前,我从未见过此内存返回给操作系统。您通常可以使用诸如top.

I suspect the behavior would be the same for Windows but I do know that Windows has other allocation functions than malloc()which may do this (part of the Win32 API).

我怀疑 Windows 的行为会相同,但我确实知道 Windows 具有其他分配函数,而不是malloc()可以执行此操作(Win32 API 的一部分)。

回答by fizzer

Other posters have commented on the platform specific angle. But since you ask specifically about malloc, lets see what the C Standard says:

其他发帖人对平台特定角度发表了评论。但是由于您专门询问 malloc,让我们看看 C 标准怎么说:

"The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation."

“free 函数导致 ptr 指向的空间被释放,也就是说,可用于进一步分配。”

Which seems a pretty clear requirement that the memory is not returned to the OS. You occasionally see programs relying on this behaviour:

这似乎是一个非常明确的要求,即内存不返回给操作系统。您偶尔会看到依赖此行为的程序:

int main(void)
{

    void *p = malloc(AS_MUCH_MEMORY_AS_I_WILL_EVER_NEED);

    if (p != 0)
    {
        free(p);
        /* malloc should always work for rest of program */
    }
}

However, when this question has come up on comp.lang.c, some posters have pointed out this section:

但是,当这个问题出现在 comp.lang.c 上时,一些发帖人指出了这一部分:

"The malloc function returns either a null pointer or a pointer to the allocated space."

“malloc 函数返回一个空指针或一个指向分配空间的指针。”

This suggests that any call to malloc may fail. It seems that the intent of the Standard is that memory is not returned to the OS, but the issue is not 100% certain in the eyes of language lawyers.

这表明对 malloc 的任何调用都可能失败。似乎标准的意图是不将内存返回给操作系统,但在语言律师看来,这个问题并不是 100% 确定的。

回答by Kipyego

The malloc function returns either a null pointer or a pointer to the allocated space."

malloc 函数返回一个空指针或一个指向已分配空间的指针。”

This suggests that any call to malloc may fail. It seems that the intent of the Standard is that memory is not returned to the OS.

这表明对 malloc 的任何调用都可能失败。似乎标准的意图是不将内存返回给操作系统。