侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论

内存的五个分区

barwe
2022-07-25 / 0 评论 / 0 点赞 / 1,045 阅读 / 1,105 字
温馨提示:
本文最后更新于 2022-07-25,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

内存的五个分区:代码、常量、静态、堆、栈。

代码区 以编译的机器码形式存放着程序的代码。函数的名称是一个指针(函数指针),它指向代码区中存放该函数的位置。

常量区 存储常量(程序运行期间不能被修改的量,例如各个数值和字符串的字面量等),只能改变常量指针指向的地址,不能改变常量指针指向位置的内容,因为常量不可被修改。

#include <stdio.h>

int main(){
    const char *p = "abcd";
    printf("%p: %s\n", p, p);
    //=> 00007ff668569000: abcd
    p = "1234";
    printf("%p: %s\n", p, p);
    //=> 00007ff66856900d: 1234
    return 0;
}

编译器在常量区 00007ff668569000 创建了一个字符串常量"abcd",并将它赋值给字符型指针 p (p = "abcd"),这里看起来是将一个字符串赋值给一个字符型指针非常不靠谱,实际上是将常量的内存地址赋值给了指针,非常靠谱。修改指针 p 的值,实际上是让指针 p 指向了另一个常量,因此 p 的指向地址发生了变化。

常量区的对象由系统自动维护,因此开发者不需要担心某个常量因为无人使用而一直得不到释放。

静态区 存放静态变量和全局变量。

// 未初始化的静态全局变量
static int a;

// 未初始化的全局变量
int b;

void test() {
    // 定义在函数内部的静态变量
    static int c = 1;
}

全局变量和静态变量只会执行一次初始化,即使test函数被多次调用,静态变量 c 只有在第一次被调用时才会初始化,其余调用该行会被忽略。

未执行初始化的全局变量和静态变量,编译器会自动给一个初始值。

静态区的内存直到程序结束才会被释放。

堆区 的空间需要程序员自己手动申请和释放,忘记释放容易造成内存泄漏。

void test() {
    // 申请一个 4 字节的空间,malloc 函数返回指向申请空间首地址的 void * 指针
    // void * 类型的指针可以转换为任意类型的指针,这里我们声明了 p 是 int * 指针
    int *p = malloc(4);
    
    // 现在我们可以将 p 当做 32 bits 整型指针使用
    
    // 使用完毕使用 free 函数释放内存区域(清空存储内容并将该空间标记为可用)
    free(p);
    
    // 此时 p 指向了一片没有分配的空间,重置 p 的指向避免野指针
    p = nullptr;
}

堆的空间按照地址递增的顺序进行分配,后申请的空间地址更大。

栈区 由编译器管理,主要用来保存函数调用的数据,例如参数、返回值和局部变量等。

0

评论区