C/C++ 内存布局

C/C++ 程序的内存布局 (Memory Layout In C/C++)

上图展示了程序中内存布局(Memory Layout)的关键构成(Key Components),其中黄色部分称为动态内存区(Dynamic memory area),其中包括堆内存(Heap)和栈内存(Stake),下面三个不同颜色的部分我们各称为一个段(Segment),整个程序有自己的虚拟内存地址空间,由操作系统映射到实际的物理内存地址,从程序自身的角度看它认为自己在运行时是占用连续的一整块内存空间,至于物理内存如何存储运行时的程序指令这是操作系统的事,这涉及到内存管理,进程调度,页面置换等内容不是接下来所说的重点。

  1. 命令行参数和环境变量 (Command-line Arguments & Environment Variables)
    位于内存结构的顶部,这些是用户在程序启动时通过命令行传递给程序的输入,例如文件路径或配置选项。环境变量则提供了程序运行环境的配置信息。允许用户在程序运行时指定程序的行为。例如,用户在命令行中输入 ./myprogram file.txt,其中 file.txt 就是一个命令行参数,程序可以据此打开指定的文件。
  2. 栈 (Stack)
    栈作为一种逻辑上符合后进先出(LIFO)的数据结构,用于管理函数调用和局部变量。当程序调用一个函数时,函数的局部变量和返回地址会被压入栈中;函数执行完毕后,这些信息会被弹出栈。栈帮助程序追踪当前的执行状态。
    注意:栈的空间有限,过多的局部变量或深度递归可能导致栈溢出(Stack Overflow)错误。
  3. 堆 (Heap)
    堆是一个动态分配的内存区域,程序可以在运行时请求和释放内存。用于存储可变大小的数据结构,如数组、对象等。程序员需要显式地分配和释放堆内存(例如使用 malloc 和 free 函数)。
    注意:如果不正确释放堆内存,可能导致内存泄漏,影响程序性能。
  4. 未初始化数据段 (Uninitialized Data / BSS)
    这个区域用于存储未初始化的全局变量和静态变量。尽管这些变量在程序中被声明,但在程序开始时没有具体的初值,通常默认被赋予零值(0 或 NULL)。
  5. 初始化数据段 (Initialized Data)
    这个区域包含已初始化的全局变量和静态变量。这些变量在程序开始执行时已经有明确的初值。
  6. 文本段 (Text Segment)
    这是程序代码所在的区域,包含了所有的可执行代码。CPU 从这个区域读取二进制指令并执行。

文本段(Text Segment)

  1. 函数代码 (Function Code)

    编译器将函数的源代码转换为机器码(即 CPU 能够理解和执行的二进制指令)。这些机器码被存储在文本段中,成为程序运行时的“指令集”。

  2. 常量和字符串 (Constants and Strings)

    程序中使用的字符串字面量(如 "Hello World")和常量(由 const 修饰如数字 42 或字符 'A')这些内容被放置在文本段中。

初始化数据段(Initialized Data Segment)

  1. 全局变量(Global Variables)
    所有显式初始化为具体值的全局变量存储在初始化数据段中。

    int global_var = 10;
    
  2. 静态变量(Static Variables)
    与全局变量类似,显式初始化为具体值的静态变量也存储在这个段中。

    static int static_var = 20;
    
  3. 常量(Constants)
    具有预定义值的常量存储在初始化数据段中。

    const int const_var = 30;
    

https://unstop.com/blog/memory-layout-in-c

https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html

https://sourceware.org/binutils/

https://www.gnu.org/software/binutils/