Stack Memory vs Heap Memory
Possible Duplicate:
What and where are the stack and heap
我正在用C++编程,我一直想知道堆栈内存和堆内存到底是什么。我只知道当我调用new时,我会从heap中获取内存。如果创建局部变量,我将从堆栈中获取内存。经过对因特网的研究,最常见的答案是栈内存是临时的,栈内存是永久的。
堆栈和堆内存模型是操作系统还是计算机体系结构的概念?所以其中一些可能不遵循堆栈和堆内存模型,或者所有的模型都遵循它?
堆栈和堆内存是对虚拟内存(可能在磁盘和RAM之间交换内存)的内存模型的抽象。那么堆栈和堆内存在物理上可能是RAM还是磁盘?那么,堆分配看起来比堆栈对应项慢的原因是什么呢?
另外,主程序将在堆栈或堆中运行?
另外,如果进程用完了分配的堆栈内存或堆内存,会发生什么情况?
谢谢
- @Meagar这确实会引发一些问题,这些问题在你所链接到的问题中没有提到。
在C++中,堆栈内存是本地变量被存储/构造的地方。堆栈还用于保存传递给函数的参数。
堆栈类似于std::stack类,您将参数推送到它上面,然后调用一个函数。然后,函数知道它期望的参数可以在堆栈的末尾找到。同样,函数可以将局部变量推送到堆栈上,并在从函数返回之前将其弹出。(警告-编译器优化和调用约定都意味着事情不是那么简单)
从一个较低的层次上理解堆栈是最好的,我建议在堆栈上使用这种组装传递参数的链接技术。很少有人会考虑C++中的任何手工堆栈操作。
一般来说,堆栈是首选的,因为它通常在CPU缓存中,因此涉及存储在堆栈上的对象的操作往往更快。然而,堆栈是一个有限的资源,不应该用于任何大的资源。耗尽堆栈内存称为堆栈缓冲区溢出。这是一件很严肃的事情,但是除非你有一个疯狂的递归函数或者类似的东西,否则你真的不应该遇到一个。
堆内存正如rskar所说。一般来说,用新分配的C++对象或用MALOC分配的内存块最终堆起来。堆内存几乎总是必须手动释放,尽管您应该真正使用智能指针类或类似的类,以避免需要记住这样做。堆内存不足,会吗?导致std::bad_alloc。
- "堆栈内存几乎总是必须手动释放。"您的意思是堆内存。另外,值得一提的是,堆内存是"全局的",当您用完堆时,其他应用程序也会用完堆。不过,堆栈具有本地作用域。
堆栈内存是通过CPU的堆栈寄存器访问的内存范围。堆栈被用作在汇编语言中实现"跳转子例程"-"返回"代码模式的一种方法,也被用作实现硬件级中断处理的一种方法。例如,在中断期间,堆栈用于存储各种CPU寄存器,包括状态(指示操作结果)和程序计数器(中断发生时,程序中的CPU在哪里)。
堆栈内存在很大程度上是常规CPU设计的结果。它的分配/释放速度很快,因为它是严格的后进先出设计。这是一个简单的移动操作和堆栈寄存器上的减量/增量操作。
堆内存只是在程序加载和分配堆栈内存后剩余的内存。它可能(也可能不)包括全局变量空间(这是惯例问题)。
现代的具有虚拟内存和内存映射设备的先发制人的多任务操作系统使实际情况更加复杂,但简而言之,这就是堆栈与堆。
- 这在很多方面都是错误的。在我所了解的任何体系结构中,"堆栈内存"和"堆内存"通常都没有任何区别。两者都可以通过堆栈指针、索引寄存器或其他方式访问。堆栈指针和索引寄存器都可以任意更改以访问进程可用的任何内存。
- @Unaperson:RAM是RAM,当然,可以更改和分配SP。"堆栈内存"更像是一个意图或角色术语,不一定是专门的硬件。顺便说一句,在6502的情况下,您的堆栈确实卡在第1页(字节256到511)。
- @是的,的确如此。我在1984年写了一个Kermit协议的实现,用6502汇编程序在bbc micro上进行了完整的vt100终端仿真(对于z80程序员来说不是一个愉快的体验),所以我知道我在这里说的是什么。
- @尤纳佩森:好吧,那么-那么,我所做的错误陈述到底是什么?
- @对于大多数架构来说,堆栈内存和普通内存没有区别。即使在6502上,您也可以(有时也必须)在"普通"内存中实现自己的堆栈——您只是不能通过调用和返回操作码来使用它。即使在6502上,堆栈内存也没有什么特别的,只是关于如何访问它(通过6502堆栈页),您似乎在暗示堆栈和其他类型的内存之间实际上存在物理差异。
- @不好意思-我从来没有打算暗示堆栈和其他类型的内存之间实际上存在物理差异。
这是一种语言抽象——有些语言既有两种语言,也有一种语言,有些语言两者都没有。
在C++的情况下,代码不在堆栈中运行,也不在堆中运行。如果堆内存不足,可以通过重复调用new在循环中分配内存而不调用delete释放内存来测试会发生什么。但在执行此操作之前,请先备份系统。
- 在试图填充堆之前"进行系统备份"?你在哪个平台上,MS-DOS?
- @拉尔斯曼,不,我在没有设置用户限制的Unix系统上花了不少钱。即使在"现代"操作系统上,它也可能会导致问题——试试看(我的附带条件)。
- @Unaperson:我以前在Unix和Linux系统上的内存不足。我从来没有遇到过什么大问题;通常只是慢了很长时间,直到一切恢复正常,有时需要重新启动。
- @拉尔斯曼,但你是否取消了对用户进程的限制?你试过了吗,比如说,窗户?对于我们大多数的Unix用户来说,"重启的必要性"是下一步。
- @Unaperson:所有系统(Linux、Mac OS X、OpenBSD)都有默认限制。不,我从不在窗户上尝试任何沉重的东西,我讨厌清理碎玻璃;)
- @拉尔斯曼,我不是说系统没有默认限制,我是说它们可以被删除,如果删除了,你就不能明智地测试它们。因此,对一个可能致命的实验(可能会导致关键的服务器进程)唯一明智的方法就是进行备份。如果你不能支持,就不要做测试。如果我在一家投资银行的交易服务器上做了这样的测试,你会怎么做?
- @尤纳佩森:啊,对。我不习惯在生产服务器上运行这样的测试,我相信我的本地计算中心不会取消对hpc集群的限制:)
- @拉尔斯曼:"我相信我的本地计算中心不会取消限制"-那你就是疯子。我真的被这个咬了一口的时候,当地的"计算机中心"(我发现你是个学者吗?)让他们不安了,我来参加了一个培训班,其中一个要素是做什么——猜猜看……
- 如果你和尤纳佩森生活在同一个星球上,那么在做这件事之前先做一个系统备份。对我们地球人来说,这是相当安全的。
- @托尼克,那将是真实的世界(事情出了问题,你必须付出代价,如果他们这样做),而不是你生活在一个快乐的,有节奏的世界,我猜。
- 我不同意这是一种语言抽象。没有用于抽象内存访问的堆x堆栈的语言。处理器有堆栈指针,C使用它们,因为这是通常的内存设计。因为C是一个"高级组件",所以使用这些内存模型是很自然的。