程序数据是如何在内存中组织的

xiaoeyv
1年前发布

程序数据是如何在内存中组织的

如图,右侧是一片内存空间,地址由下往上升高。
具体参数:

  • Kernel

    • 代表操作系统的核心源码

1. Text(代码区)

  • 作用Text 区域存储程序的可执行代码,也就是程序的指令集。在 C 语言中,它包含了所有的函数体,如 main 函数、sum 函数以及程序中的字符串常量等。
  • 特点

    • 只读:代码区通常是只读的,这是为了防止程序在运行时修改自己的代码,增加安全性。
    • 不可变:一旦程序加载到内存,Text 区的内容通常不会发生变化,除非程序被重新编译。
    • 存储结构:存储的是指令和常量数据,如字符串 "Hello world!"
  • 示例

    int sum(int x, int y) {
        return x + y;
    }

    sum 函数存储在 Text 区域,它包含了程序的计算逻辑。在程序执行时,CPU 会从 Text 区读取并执行这些指令。

2. Data(数据区)

  • 作用Data 区域存储初始化过的全局变量和静态变量。所有在程序中显式初始化的全局变量会存储在这个区域。
  • 特点

    • 初始化变量:如果你声明并初始化了全局变量,它们会被存储在 Data 区。例如 char* str = "Hello, world!"; 中的 str 就是一个全局变量。
    • 持久性:这些变量在程序运行时会一直存在,并且在不同的函数之间共享。
  • 示例

    char* str = "Hello, world!";  // 这部分存储在Data区

    str 是一个初始化的全局变量,它存储在 Data 区,初始化时指向字符串 "Hello, world!"

3. Bss(未初始化数据区)

  • 作用BSS 区域存储未初始化的全局变量或静态变量。它们在程序开始时没有显式地被赋值,但在程序执行时,操作系统会为它们分配零值(默认值)。
  • 特点

    • 未初始化变量:在程序编译时,所有未初始化的全局变量和静态变量都会存储在 BSS 区。例如,声明一个全局变量但没有赋值,它就存储在 BSS 区。
    • 默认值为零BSS 区的变量在程序加载到内存时会被初始化为零或空指针(视类型而定)。
  • 示例

    int glb;  // 这部分存储在BSS区,未初始化

    glb 是一个未初始化的全局变量,它会存储在 BSS 区,并在程序开始时默认被初始化为 0。

4. Heap(堆区)

  • 作用Heap 区用于动态内存分配。当程序运行时,需要分配内存时(例如通过 mallocnew),这些内存会被分配到堆区。程序员需要手动管理这些内存,使用 freedelete 来释放。
  • 特点

    • 动态分配Heap 区的内存大小是动态变化的,取决于程序运行时的内存分配需求。
    • 管理复杂:程序员需要自行管理堆内存,否则可能会导致内存泄漏(未释放的内存)或悬挂指针(指向已释放的内存)。
  • 示例

    int* ptr = malloc(10 * sizeof(int));  // 动态分配内存,存储在Heap区

    通过 malloc 分配的内存会存储在 Heap 区。在此例中,ptr 指向堆区分配的内存空间。

5. Shared Libraries(共享库)

  • 作用Shared Libraries 区域存储程序在运行时加载的共享库。共享库包含了多个程序共享的代码,减少了内存的使用。操作系统会在程序加载时把这些共享库加载到内存中,并将它们映射到程序的地址空间中。
  • 特点

    • 动态链接:共享库在程序运行时被动态链接,不同程序可以共享同一个库,节省内存。
    • 共享代码:多个程序可以同时使用同一个库的代码,避免了重复加载。
  • 示例
    假设程序中使用了 printf 函数,这个函数通常会从标准 C 库(如 libc)中加载。libc 就是一个共享库。
    共享库的代码通常会存储在程序的内存区域中,当程序调用 printf 时,会跳转到 libc 中对应的实现。

6. Stack(栈区)

  • 作用Stack 区用于存储函数的局部变量、函数参数以及返回地址。当函数被调用时,栈会存储该函数的返回地址、局部变量以及其他调用信息。栈在函数调用时自动分配,并在函数返回时释放。
  • 特点

    • 自动管理:栈区的内存由操作系统自动管理,程序员不需要手动分配和释放。
    • 先进后出:栈的内存分配遵循 LIFO(后进先出)原则,每当一个函数调用时,栈会压入相应的信息;当函数返回时,栈会弹出这些信息。
    • 溢出问题:栈的大小是有限的,如果栈空间过大(例如递归深度过深),可能会导致栈溢出(stack overflow)。
  • 示例

    void sum(int a, int b) {
        int c = a + b;  // 局部变量c存储在栈区
    }

    函数 sum 的参数 ab 和局部变量 c 都存储在栈区。当函数执行时,它们会被压入栈;函数返回后,它们会从栈中弹出。

总结:

  • Text 区存储程序的可执行代码。
  • Data 区存储已初始化的全局变量。
  • BSS 区存储未初始化的全局变量。
  • Heap 区存储动态分配的内存。
  • Shared Libraries 区存储共享库。
  • Stack 区存储函数的局部变量、参数和返回地址。
© 版权声明
THE END
喜欢就支持一下吧
点赞 0 分享 收藏
评论 抢沙发
OωO
取消