堆栈内存与堆内存

Ste*_*eng 89 c++ memory

可能重复:
堆栈和堆的内容和位置

我用C++编程,我总是想知道堆栈内存与堆内存到底是什么.我所知道的就是当我调用new时,我会从堆中获取内存.如果创建局部变量,我会从堆栈中获取内存.经过对互联网的一些研究,最常见的答案是堆栈内存是临时的,堆内存是永久性的.

堆栈和堆内存模型是操作系统或计算机体系结构的概念吗?那么它的一些可能不会遵循堆栈和堆内存模型或所有它们都遵循它?

堆栈和堆内存是虚拟内存的内存模型的抽象(可能在磁盘和RAM之间交换内存).堆栈和堆内存在物理上可能是RAM还是磁盘?那么堆分配似乎比堆栈对应慢的原因是什么?

此外,主程序将在堆栈或堆中运行?

此外,如果进程耗尽堆栈内存或堆内存分配,会发生什么?

谢谢

Eoi*_*oin 58

在C++中,堆栈存储器是存储/构造局部变量的地方.堆栈还用于保存传递给函数的参数.

堆栈就像std :: stack类一样,你将参数压入它然后调用一个函数.然后,该函数知道它可以在堆栈末尾找到的参数.同样,该函数可以将locals推入堆栈并在从函数返回之前将其弹出.(告诫 - 编译器优化和调用约定都意味着事情并非如此简单)

堆栈最好从低级别理解,我推荐这个链接Art of Assembly - 在堆栈上传递参数.很少有人会考虑使用C++进行任何类型的手动堆栈操作.

一般来说,堆栈是首选,因为它通常在CPU缓存中,因此涉及存储在其上的对象的操作往往更快.但是堆栈是有限的资源,不应该用于任何大的.耗尽堆栈内存称为堆栈缓冲区溢出.这是一个严肃的事情,但你真的不应该遇到一个,除非你有一个疯狂的递归函数或类似的东西.

堆内存就像rskar所说的那样.一般来说,在使用new分配的C++对象中,或者使用malloc等分配的内存块最终会在堆上.堆内存几乎总是必须手动释放,但你应该重新使用智能指针类或类似的东西,以避免需要记住这样做.耗尽堆内存可以(将?)导致std :: bad_alloc.

  • "堆栈内存几乎总是必须手动释放." 你的意思是堆内存.另外,值得一提的是堆内存是"全局"的,当你用完堆时,其他应用程序也会耗尽堆.但是,堆栈具有本地范围. (15认同)

rsk*_*kar 31

堆栈存储器特别是可通过CPU的堆栈寄存器访问的存储器范围.Stack用作实现汇编语言中"Jump-Subroutine" - "Return"代码模式的一种方式,也是实现硬件级中断处理的一种方法.例如,在中断期间,堆栈用于存储各种CPU寄存器,包括Status(表示操作结果)和Program Counter(中断发生时程序中的CPU).

堆栈内存是通常的CPU设计的结果.分配/解除分配的速度很快,因为它严格地是后进/先出设计.在堆栈寄存器上移动操作和递减/递增操作很简单.

堆内存只是加载程序并分配堆栈内存后遗留的内存.它可能(或可能不)包括全局变量空间(这是一个惯例问题).

具有虚拟内存和内存映射设备的现代先发制人多任务操作系统使实际情况更加复杂,但简而言之就是Stack vs Heap.

  • @unapersson:道歉 - 我从来没有打算暗示堆栈和其他类型的内存之间实际存在物理差异. (7认同)
  • @rskar对于大多数架构,堆栈内存和普通内存之间没有区别.即使在6502上,您也可以(有时必须)在"普通"内存中实现自己的堆栈 - 您无法通过调用和返回操作码来使用它.即使在6502上,堆栈内存也没什么特别之处,只关于它是如何被访问的(通过6502堆栈页面)你似乎在暗示堆栈和其他类型的内存之间实际存在物理差异. (5认同)
  • 这在很多方面都是错误的.在我所知道的任何架构上,"堆栈内存"和"堆内存"之间通常没有任何区别.两者都可以通过堆栈指针,索引寄存器或其他任何方式访问.堆栈指针和索引寄存器都可以任意更改,以访问进程可用的任何内存. (3认同)

小智 3

这是一种语言抽象——有些语言两者都有,有些语言两者都有,有些则两者都没有。

对于 C++,代码既不在堆栈中运行,也不在堆中运行。new您可以通过在循环中重复调用分配内存而不调用释放内存来测试如果delete耗尽堆内存会发生什么情况。但在执行此操作之前请先进行系统备份

  • 在尝试填充堆之前“进行系统备份”?你在什么平台上,MS-DOS? (67认同)
  • @unapersson:所有系统(Linux、Mac OS X、OpenBSD)都有默认限制。不,我从不尝试在 Windows 上做任何繁重的事情,我讨厌清理碎玻璃;) (6认同)
  • @larsman但是你取消了对用户进程的限制吗?您是否在 Windows 等设备上尝试过?对于我们大多数 Unix 人来说,“必须重新启动”是被解雇的下一步。 (4认同)
  • @unapersson:啊,对了。我不习惯在生产服务器上运行此类测试,并且我相信我的本地计算中心不会取消对 HPC 集群的限制:) (2认同)
  • @TonyK 那将是现实世界(如果事情出错,你就必须付出代价),而不是你生活的快乐的世界,我猜。 (2认同)