为什么内存会分成堆栈和堆?

Why is memory split up into stack and heap?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What and where are the stack and heap

我有几个关于堆栈和堆的问题。

要知道的基本情况是,堆栈比堆快,但有限。(如果我错了,请纠正我)。

然而,我总是想知道堆栈和堆究竟是如何工作的。RAM只是内存的一块,它不分为"stack"和"heap"(还是?)如果是这样,我们为什么要首先将内存分成堆栈和堆?

操作系统只允许我们分配堆栈上的所有东西->一切都会更快->幸福世界?

我很确定情况并非如此。但是为什么呢!有人能给我一个深入的答案吗?

很抱歉,如果这篇文章是某个人写的文章的副本,那么有太多与stack和heap相关的内容,我找不到确切的问题。如果你碰巧认识一个,就去链接它。


堆栈:堆栈被用作一种临时的临时临时临时草稿,供当前正在执行的代码块、称为当前块的任何块以及称为当前块的任何块使用,依此类推。当当前块退出时,它使用的局部变量将被忽略。顾名思义,堆栈以后进先出的方式使用。

堆栈最重要的用途之一是跟踪当前的调用链。当一个函数调用另一个函数时,调用者将下一条指令的地址(返回地址)推送到堆栈上。当每个函数退出时,它从堆栈中弹出调用方的返回地址,并继续从该地址开始执行代码。它还用于在调用者和被调用者之间通信函数参数和返回值。

堆:堆是不同的——没有特定的顺序。如果您想在一个代码块中分配内存,并让内存停留在块的末尾之外,那么您可以在堆中分配它。当然,您还需要将指向它的指针/引用存储在某个地方,以便其他代码可以找到该内存;大多数语言都提供了这样的适应能力。

速度:速度的差异并不是由于内存本身的任何属性造成的——正如您在问题中所说,堆栈和堆通常都位于同一物理内存中。由于堆栈的后进先出(lifo)特性,在堆栈上分配空间很快:如果将某个东西推到堆栈上,则只有一个地方可以结束。相反,在堆上分配块需要在内存中找到足够大的连续可用区域。堆栈分配可以像单个指令一样快;堆栈分配需要调用像malloc()这样的内存分配函数。

静态与动态:在堆上分配内存是动态的——是否分配一个块,以及块的大小,可以根据程序运行时接收到的输入来确定。如果需要,甚至可以调整堆上分配的内存区域的大小。也可以在堆栈上动态分配内存(参见C标准库函数alloca()),但是一旦当前函数退出,内存就会丢失。堆栈分配通常是静态的——编译器确定(非寄存器)参数、返回数据和局部变量需要多少空间,并生成代码,以便在调用函数时在堆栈上保留必要的空间。

示例:假设您正在创建字处理器。您不能提前知道文档将有多大,甚至不能知道同时使用多少文档。同时,您希望用户的文档保持在内存中,只要用户想保持它们的打开状态。如果试图为堆栈上的文档分配内存,您会发现很难同时打开多个文档,并且需要创建一个创建、编辑、保存和关闭文档的函数。在堆上分配空间可以让您创建任意多的文档,每个文档的大小都适合它所包含的数据,并避免将文档的生存期与任何特定函数的生存期绑定在一起。

总结:简而言之,堆栈保存变量的值(有时使用寄存器),而堆用于分配将在当前块的生存期之后使用的内存。


不能只使用堆栈,因为堆栈需要后进先出分配和解除分配顺序(即,只能解除分配最新分配的数据;在堆栈中,不能解除分配一些旧数据并保留一些新数据)。

实际上,您可以去掉堆栈(只保留堆)。看阿佩尔的废纸收集可以比堆栈分配和他用续书编译更快。

堆没有定义好的含义(除了"不在堆栈上的动态分配内存")。实际上,在Linux系统上,使用mmap系统调用分配大量内存是相当快的(但是malloc实现试图避免mmap并更喜欢重用freed内存)。问题是小内存区域的分配。

阅读更多关于垃圾收集技术的内容。在C或C++中,你可以使用勃姆的气相色谱法。

堆栈通常很有用,特别是对于递归函数调用。它非常有用(例如在C语言中),以至于今天的处理器通常都有一个专用的堆栈指针寄存器(由调用和返回机器指令使用)。但情况并非总是如此;在某些处理器(如IBM360)上,堆栈指针是常规寄存器,而不是硬编码寄存器。

另请参见此回答(和其他回答)有关虚拟地址空间的问题。


两种方法的内存都是相同的,但是堆栈和堆是两种不同的数据结构,它们对于不同的用途都很有用。

堆栈是一种非常原始的抽象,任何微处理器都需要它来在几个操作数(通常是处理器寄存器或内存地址)上执行指令。

堆是一个通用的分配内存区域,通常您希望在其中存储未绑定到堆栈的数据,也就是说,如果存储在堆栈中,则它们的生存期更长,或者换句话说,数据将由代码的不同部分访问。