堆栈由编译器或操作系统/架构创建

Posted

技术标签:

【中文标题】堆栈由编译器或操作系统/架构创建【英文标题】:The stack is created by compiler or OS/architecture 【发布时间】:2011-04-06 02:12:47 【问题描述】:

这个问题是我上一个问题的后续问题

stack growth direction

我想知道堆栈是由编译器还是操作系统/架构创建的?另外,操作系统如何知道这些编译器特定的东西?例如:C++ 允许变量在堆栈和堆上创建数据,而 java 只允许堆。

如果堆栈是在堆上创建的,如帖子中所述,系统如何知道它,因为系统只知道堆栈指针和基指针。

【问题讨论】:

What and where are the stack and heap的可能重复 从 Java 的角度看,我看不出这两个问题是如何联系起来的。您确实意识到 JVM 有效地充当 Java 世界中的平台/架构,是吗? @Byron 这只是我之前问题的后续。问题也不在于了解堆栈。在我之前的帖子中,有人说可以在堆上创建堆栈以防止缓冲区溢出之类的事情。那么如果在堆上创建,系统怎么知道呢? @brett,是的,很明显您需要基本了解堆栈和堆是什么。仔细阅读欺骗答案。您可以在堆中创建特定的堆栈数据结构,但这不是我们正在谈论的基本堆栈结构。 @brett,我刚刚阅读了您最后接受的答案中的 cmets。内存都是一样的,但从概念上讲,栈 = 编译时分配的内存,堆 = 动态分配的内存。我希望这很清楚。 【参考方案1】:

堆栈是操作系统为您的程序分配的内存位置。一旦它被分配,操作系统会设置一个寄存器(在 x86 上,它是esp)到堆栈所在的位置,然后它会启动你的程序。编译器知道,如果他们使用这个寄存器中的值作为堆栈指针,他们会没事的。然后他们做任何他们想做的事。操作系统只是分配一个区域。它不关心它之后如何使用。

操作系统不知道您的程序将主要使用堆栈还是堆。然而,由于大多数编程语言以某种方式使用堆栈,它知道它应该分配一个。例如,Java 将其对象存储在堆上,但 JVM 的大多数实现将使用堆栈来维护调用帧(和原始局部变量),因此它也需要堆栈。

【讨论】:

对于 Java,它应该读作 一个堆栈,因为我们为每个正在运行的线程有一个 jvm 堆栈。 在可执行文件头中通常有一个用于主线程堆栈大小的字段(该字段由编译器设置,通常可以使用链接器选项设置)。此外,在创建堆栈时,通常可以设置线程堆栈大小。 JVM 线程堆栈可能与实际的 java 程序内存相同,也可能不同。这说起来很复杂,但是 JVM 可以为每个 java 线程从它用于其本机代码的系统堆栈中跟上一个单独的堆栈。【参考方案2】:

堆栈最明确地由编译器定义,操作系统为它分配空间,但这相对微不足道。堆栈是内存中的一个专用位置,编译器使用它(编译器定义使用它的指令)来控制程序执行流程和存储局部变量等。

所以操作系统不知道编译器特定的东西。堆栈仍然存储在主内存中,它不是您(程序员)可以直接控制的内存的一部分。

【讨论】:

【参考方案3】:

为虚拟机中的每个线程创建一个 Java 虚拟机堆栈。堆栈存储,除了帧的push和pop操作外,不能直接操作内容。

每次调用消息时都会创建框架,用于存储数据和部分结果,以及执行动态链接、方法返回值和调度异常。

语言规范详细说明,Java 虚拟机堆栈类似于 C 等传统语言的堆栈。所以对我来说,很明显 jvm 堆栈模型是在 jvm 实现中编码和使用的,而不是由主机操作系统提供的。

【讨论】:

【参考方案4】:

传统上,堆栈是放置机器代码调用的返回地址的位置(因此它可以在完成后返回)。因此,有一些指令可以轻松访问内存中的这个位置。

很快发现,将参数与返回地址一起放入调用是一种非常简单有效的方法。这已经发展到处理本地地址等。

【讨论】:

以上是关于堆栈由编译器或操作系统/架构创建的主要内容,如果未能解决你的问题,请参考以下文章

Unity项目技术方案Dots架构方案简介

c++堆栈的各自大小,堆和栈的各自定义

系统架构——多线程的应用

关于堆栈的讲解

堆栈的详细讲解

看看有趣的ONOS Ⅲ:系统组成