首页 > 解决方案 > 为什么使用内存布局来运行 C 程序

问题描述

据我所知,当 C 程序运行时,avirtual memory是用stack segmentfor local variableheap动态分配、text segment代码、data segmentforstatic variableglobal variable. 我不明白为什么我们必须将我们的记忆分成stack,heap和? 哪个创建,操作系统还是编译器?而且据我了解,当我们运行裸机嵌入式程序时,我们将在物理内存上运行,所以我们不会有,,在这里,对吗?data segmenttext segmentvirtual memorystackheapdata segment

标签: cmemorystackembeddedheap-memory

解决方案


堆栈、堆、数据和文本都位于物理内存中,与它没有区别。内存被分配用于不同的目的,在范围和持久性方面具有不同的行为,并有助于链接器将内存分段(或划分)用于不同目的。

在许多嵌入式系统中,代码(文本段)和常量数据驻留在与 RAM物理不同的 ROM 中。链接器需要知道 ROM 空间在内存映射中的位置。

堆栈是用于本地数据存储、函数参数和返回调用/函数地址的临时空间。当函数被调用和变量进出范围时,它会被不断地使用和重用。

堆用于通过malloc()/等函数进行动态内存分配free()。它是在运行时分配的内存,而不是在堆栈上静态分配或自动分配的内存。堆分配一直存在,直到它们显式返回到堆而不是具有“范围”并被自动实例化和销毁。

数据段是静态分配的数据所在的位置。这是静态和全局数据所在的位置。此内存中的对象在程序启动时被实例化,并在代码执行期间持续存在。

在实践中,静态数据通常有两个段,databss. data用于显式非零初始化数据。它们存在于读/写内存中,但该内存的初始化值在text. 当程序启动时,之前 运行的启动代码main()将初始值复制到分配的 RAM 段中。该bss段被简单地初始化为零 - 静态数据的默认初始值。

所以:

  • bss并且data必须是不同的空间以促进有效的初始化。
  • text必须是不同的,因为它在 ROM 中或在将其加载到 RAM 中的系统中就地定位和执行,通过将连续的代码块复制到运行时位置可以最有效地完成。
  • heap是一个运行时内存池。当然可以将堆分布在不连续的内存中,但在简单的情况下,它通常是单个连续块。
  • 堆栈概念是(大多数)微处理器如何在机器级别工作的人工制品,因此它是编译语言的自然模型。stack段本身是main()线程中使用的调用/数据堆栈。一些处理器切换到单独的堆栈以进行中断处理(有些则没有)。如果使用多线程,通常每个线程都有自己的堆栈。例如,这些线程堆栈可以从堆中动态实例化或静态分配bss

关键是 C 代码被编译为目标代码,然后链接形成最终的二进制可执行文件。链接器负责定位代码和数据,因此需要一个内存映射来知道将什么放在哪里。堆栈必须是连续的,因为这就是机器的工作方式,并且它是本地自动创建和销毁的数据所必需的。


推荐阅读