如何堆叠,实现,分配堆和堆栈内存

时间:2009-07-31 15:39:54

标签: c++ c memory-management heap-memory stack-memory

  

可能重复:
  How is heap and stack memories mananged, implemented, allocated?
  Stack,Static and Heap in C++

在C / C ++中,我们可以在堆栈或堆上存储变量,函数,成员函数,类的实例。

每个如何实施?如何管理(高级别)? gcc是否预先分配了一大块内存用于堆栈和堆,然后根据请求发送?原始内存是否来自RAM?

是否可以在堆上而不是堆栈上分配函数?

             --Clarification--

我真的在询问堆和堆栈内存的实现和管理。 After reading referenced question,我找不到任何解决这个问题的内容......感谢链接

1 个答案:

答案 0 :(得分:10)

我认为你的问题可以很容易地写出关于操作系统的书的一些章节。我建议你阅读Tanenbaum:现代操作系统。

堆和堆栈的主要区别,一个是每个进程项,另一个是每个线程项。最初,当程序启动时,它会获得一些最小的堆和一些堆栈段。堆增长,堆栈是静态的(对于每个线程)。如果你编写一个不终止的递归函数(无限递归)你将得到堆栈溢出;)任何函数调用在堆栈段上都有一个堆栈帧,当函数离开时,堆栈被展开并且框架可以自由使用下一个功能。堆栈是一种连续的线性结构。在Linux上,您可以通过环境变量为进程配置堆栈段大小。在Windows上(至少使用MS Visual C ++),您可以传递具有堆栈段大小的链接器标志。在编译时分配一些大数组时也可以产生堆栈溢出:

char test[1000000];

堆是一个不同的故事。当进程启动时,堆大小是一些默认值,并且可能因操作系统或操作系统上使用的配置而异(例如,在Windows上,默认情况下它是2MB,据我所知)。此外,如果您需要更多堆,为变量等分配更多空间,它将会增长。如果程序没有释放堆内存,它就会耗尽它(或堆空间)。堆实现有不同的数据结构,其中一些是二叉树衍生物,有些不是例如。斐波纳契堆(树木的福雷斯特)。您可以阅读有关如何编写内存分配器的一些文章等。必须优化这些数据结构,以便在需要取消分配已分配的块时查找堆节点,或者在需要新的堆空间时附加(查找空闲块)。

32位操作系统上的每个进程都有4GB的虚拟地址空间。可以想象,没有那么多的RAM可以满足所有具有4GB虚拟地址空间的进程。操作系统内存按页面组织,不再需要或过期时可以交换为HD。这就是分页发挥作用的地方。一切都映射到页面:堆栈或不断增长的堆的进程。由于它动态增长的堆结构,它可以放在多个页面上。这就是为什么堆访问可能非常昂贵的原因,因为如果页面不在内存中,则会发生页面错误,并且操作系统必须从磁盘加载页面(这可能会更慢)。正在执行的线程的堆栈帧位于处理器缓存中,这比RAM快得多。

不同的堆类型是可能的,对于小型对象或堆,可能存在非常快的堆,这些堆在多线程环境中非常有效。 Alexandrescu在“Modern C ++ Design”中描述了如何开发小对象分配器和管理小对象的堆。这个实现可以在他的Loki C ++库中找到。一些嵌入式系统提供物理上不同的内存区域,其中可以在顶部实现不同的堆类型。如果你想击败编译器,编写一个自己的分配器(堆管理器等)是一项艰巨的工作。

的问候,
Ovanes