美文网首页
C语言程序内存布局

C语言程序内存布局

作者: 猿耕记 | 来源:发表于2020-01-09 20:57 被阅读0次

    C语言笔记之02-C语言程序内存布局

    我们知道C语言的编译过程分为:预处理-编译-汇编-链接-生成可执行文件,而这个可执行文件由代码段(text)、数据段(data)、BSS段(bss)三部分组成。在执行可执行文件的时候,需要将这个可执行文件装配到内存中才能运行,这个中间涉及到一个C程序的内存的布局,主要是变量、常量和函数的存放位置,因此需要搞懂它的内存布局,才能很好理解程序的内存结构和优化。

    内存映射

    下图是C程序的内存模型

    Linux下32位环境的用户空间内存分布

    代码段(text)

    代码段存放的是可执行文件的可执行指令,从图中可以看出,代码段是放在内存最低地址处,这段区域是只读区域,也是可共享的。装配时直接将该段代码直接拷贝到内存的.text区。

    常量区(data)

    常量段也是整个数据段的一部分,主要存储常量和字符串常量,该段也是只读区域。

    全局数据区(data)

    全局数据区也是数据段的一部分,主要存储全局变量、static变量,该段有两部分组成:可读写数据区和只读数据区。

    未初始化数据区(bss)

    bss存放未初始化的全局变量和static变量

    堆段(heap)

    heap是写程序中经常遇到的一个区域,这块区域是动态内存分配区,堆地址从内存低地址往高地址增长,完全由程序猿自己分配和释放,这个地方一般最容易出现内存没有释放导致程序crash。在C语言中经常使用的函数就是malloc/calloc/realloc/free.

    栈段(stack)

    stack是函数执行和调用中打交道最多的地方,这块区域专门存放函数的参数、局部变量,栈的地址是由高到底进行分配,与堆正好相反。一般程序中的栈空间是有限的,其只是程序的一个临时存储区,所以在函数内部申请大的内存必须要使用堆来申请,切记不能使用数组来申请大的空间。

    实例

    一般面试题经常会考到的地方就是关于字符串常量的指针是否相等,如这个例子中的str1、str3,str7,str8是指向同一个内存地址。

    #include <stdio.h>
    #include <stdlib.h>
    
    char *str1 = "helloworld"; //字符串helloworld放在已初始化数据区(常量区),str1放在全局数据区
    char str2[] = "helloworld";//字符串helloworld和str2放在全局数据区
    static char *str3 = "helloworld";//字符串helloworld放在已初始化区(常量区),str3放在全局数据区
    static char str4[] = "helloworld";//字符串helloworld和str4放在全局数据区
    char *str5;//str5放在全局未初始化数据区
    static char *str6;//str6放在全局未初始化数据区
    int a1;//全局未初始化数据区
    static int a2;//全局未初始化数据区
    const char *str11;//全局未初始化数据区
    
    int main(int argc, char **argv){
        static char *str7 = "helloworld";//helloworld是字符串常量放在常量区,str7放在全局数据区
        char *str8 = "helloworld";//helloworld是字符串常量,str8放在栈区
        char str9[] = "helloworld";//helloworld不是字符串常量,都放在栈区
        char *str10 = (char *)malloc(sizeof("helloworld"));//str10放在堆区
        const char *str12;//栈区
        char *str13;
    
        printf("str1 %p, str2 %p, str3 %p, str4 %p\n", str1, str2, str3, str4);
        printf("str5 %p, str6 %p\n", str5, str6);
        printf("a1 %p, a2 %p\n", &a1, &a2);
        printf("str7 %p, str8 %p, str9 %p, str10 %p\n", str7, str8, str9, str10);
        printf("str11 %p, str12 %p, str13 %p\n", str11, str12, str13);
    
        if (str10){
            free(str10);
            str10 = NULL;
        }
        return 0;
    }
    
    
    

    这个例子中最容易混淆的地方就是char str9[] = "helloworld",数组形式定义的并不是字符串常量。

    参考

    相关文章

      网友评论

          本文标题:C语言程序内存布局

          本文链接:https://www.haomeiwen.com/subject/vejuactx.html