【问题标题】:Code, static, stack and heap segments implementation代码、静态、堆栈和堆段实现
【发布时间】:2014-08-12 14:41:43
【问题描述】:

我知道每个部分的用途,但我想知道实际上用 c 或 c++ 等语言实现了它们?

它们是由 c/c++ 编译器程序员在编写语言的实现时编写的吗?或者这些段是在操作系统/硬件级别实现的(也许当操作系统为程序选择地址空间时)?

我将堆栈帧想象成一个简单的 c 结构体,每次函数调用都会将其压入堆栈。我把堆想象成一个动态数组等等......

【问题讨论】:

  • C 还是 C++?选一个。这些是具有不同实现的不同语言。
  • @πάνταῥεῖ:这不是一个答案吗?

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


【解决方案1】:

这有点粗略 - 硬件架构、内存模型等都会影响 C/C++ 实现可能具有“段”的方式。较旧的 CPU 有局限性,导致一组更复杂的“段”(iAPX 286 - 还记得吗?)所以只是粗略介绍一下,谷歌搜索流行语,...

目标代码包含由可执行语句产生的代码:由汇编机器指令产生的字节。这将进入一个代码段,这将(通常)导致一个写保护的内存段。

目标代码包含数据:由组装数据定义语句产生的字节,带有一些初始化(或默认值,在 C/C++ 的情况下为零),这将进入数据段,没有访问限制。

您的 CPU 工作方式需要堆栈:将返回地址压入堆栈,通过压入函数参数进行参数传递的最有效约定也是如此。 “堆栈帧”部分是“约定俗成的”,但通常由返回地址和参数组成;为局部变量保留了额外的空间:每个实例化一组(如果函数是递归的,这很重要)。

堆只是提供分配(malloc、new)的内存区域。它通常分配在代码和数据段之外。堆栈可能会从堆中取出 - 这取决于您是只有一个堆栈段还是多个(想想线程)。

此外,请注意有几种目标代码“格式”或“语言”,即这些段在目标代码中的定义方式。这取决于系统的加载器可以处理什么:一种这样的格式称为“a.out”,另一种是“ELF”。编译器必须遵守格式和可能性。

【讨论】:

  • 虽然很有趣,但我认为您没有回答这个问题。
  • @LightnessRacesinOrbit 当然,简短的回答是“基于操作系统设计者选择的对象格式设计的编译器设计者”。 (我认为,这是你可以说的最大值,无需详细说明。)
【解决方案2】:

它们是由 c/c++ 编译器程序员在编写语言的实现时编写的吗?或者这些段是在操作系统/硬件级别实现的(也许当操作系统为程序选择地址空间时)?

段入口点主要在工具链的链接阶段(和链接器程序)进行管理。

从这个意义上说,是的,这些是由编译器开发人员实现的。

您可以提供自己的链接描述文件,您可以在其中指定这些段应该出现在哪些具体内存地址,以及这些内存地址是指 ROM 还是 RAM。

我将堆栈帧想象成一个简单的 c 结构体,每次函数调用都会将其压入堆栈。我把堆想象成一个动态数组等等......

这根本不是那么简单恐怕:

  • 堆栈帧通常还需要跟踪本地实例化的变量、堆栈展开异常所需的信息等。
  • 堆分配内存需要一些基本机制来跟踪分配的内存块及其实际大小。
  • 静态内存初始化和类初始化需要运行静态实例化类的构造函数。

【讨论】:

    猜你喜欢
    • 2012-11-05
    • 2018-05-30
    • 2013-01-25
    • 2011-08-03
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 2010-11-27
    相关资源
    最近更新 更多