UNIX与Windows内存释放

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

Windows上,我知道内存实际上被返回到操作系统。

这两种做事方式有没有很大的区别,还是做同一件事情的两种不同方式? 如果这两种方法有什么优点/缺点,它们是什么?

编辑:谢谢澄清。 我一直认为这是一个操作系统的东西(因为在类似UNIX的系统中,进程似乎不会减小,而是在Windows中)。

Solutions Collecting From Web of "UNIX与Windows内存释放"

Windows和Unix之间没有太大的区别。

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

要将内存返回到操作系统,首先将从这些大块中分配的所有内存都释放到运行时库中。 如果需要,运行时库可以告诉操作系统释放这块内存。

在Linux上,你有brkmmapbrk控制分配给你的进程的大块内存的大小; 你可以扩大或缩小它,但只能在一端。 malloc传统上扩展了这块内存,当它需要更多的内存来分配,并尽可能缩小内存。 但是,收缩并不容易; 它在最后需要一个单字节的错误时间分配,使得即使分配之前的所有内容都被释放,也不能收缩。 这是“Unix不释放内存”的来源。

不过,也有匿名的mmap 。 匿名mmap从操作系统请求一块内存,可以放在进程内存空间的任何地方。 这个块可以在不需要的时候轻松地返回,即使有后来的分配还没有被释放。 malloc还使用mmap (特别是对于大型分配,在释放后可以轻松返回一大块内存)。

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

请注意,我知道更多关于Windows比Unix下面…

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

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

作为一个例子,在Windows上,每个线程开始(默认)为其分配一个兆字节的堆栈空间。 这并不意味着每个线程都占用机器物理内存的兆字节:只是简单地将地址空间设置为可供使用。 从这个意义上讲,并不是真的可以考虑操作系统给你的程序存储器,然后程序给它回来 – 它只是不这样工作。

这完全取决于您使用的是哪个C运行时库。 没有具体的UNIX方式或WINDOWS方式。 每个编译器厂商(HP,SUN,MS,GNU)都附带自己的包含malloc逻辑的运行时库。 malloc的每个实现将根据操作系统的不同而不同。 无论是UNIX / LINUX / Windows都需要一个免费的“实际返回”的内存回操作系统。 这将是太昂贵(因为你的alloc()将在非常小的块)

最近mozilla Firefox从* BSD OS借用了一个malloc()实现。 他们选择使用不同于他们的编译器厂商(本例中是gcc和VC ++)的malloc。 既然他们想要某种行为,他们就得到了他们想要的东西。

从这个内存管理文章

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

那篇文章确实表明,在Windows中,至少对于C程序来说,内存不会被返回到操作系统。

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

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

唯一的操作系统,你不能轻松地分配内存回到系统是OS X – 引用Firefox 3内存使用情况 :

在经过苹果员工的广泛测试和确认后,我们意识到分配器没有办法在保留地址范围的前提下将未使用的内存页返回。(您可以取消映射并重新映射它们,但会导致一些竞争条件,并且不会)。有些API声称可以这么做(madvise()和msync()),但实际上并没有做任何事情。

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

请注意,上面的解释并不准确:确切地说,您需要知道物理内存,虚拟内存等之间的区别。这里有很好的解释:

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

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

我从来没有见过这个内存返回到操作系统,直到进程终止。 通常你可以用top等工具来看这个。

我怀疑这个行为对于Windows来说是一样的,但是我知道Windows有其他的分配函数,而不是malloc()可能会这样做(Win32 API的一部分)。

其他海报评论平台的具体角度。 但是,既然你问了malloc的具体问题,那么让我们来看看C标准所说的:

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

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

 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 */ } } 

然而,当这个问题出现在comp.lang.c上时,一些海报指出了这一部分:

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

这表明任何对malloc的调用都可能失败。 标准的目的似乎是内存不归还给操作系统,但这个问题在语言律师眼中并不是100%确定的。

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

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