前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >静态内存区域解析

静态内存区域解析

作者头像
谦谦君子修罗刀
发布2018-05-02 10:30:59
7570
发布2018-05-02 10:30:59
举报

通常在代码中产生的bug,往往是源于概念不清晰。知己知彼百战不殆,对内存这块了如指掌,能极大优化代码的性能。

一、内存四区建立流程讲解

如上图所示,首先操作系统要把物理硬盘代码加载到内存中,加载完成后,操作系统会将代码分成四个区域,即堆区、栈区、全局区和常量区。最后,操作系统会找到main函数入口执行程序。这就是内存四区执行流程的说明。

二、内存四区存储说明 栈区:由编译器自动分配释放,存放函数的参数值、局部变量等。 堆区:由程序员动态申请与释放内存,通常用于存放new/malloc关键字创建的值。如果程序员不释放,程序结束时会由操作系统回收。 全局区:也叫静态区,用于存放常量和全局变量,由操作系统管理。全局变量和静态变量存储在一起,初始化的全局变量和静态变量在同一块区域,未初始化的存储在相邻的另一区域内。 程序代码区:存放函数体的二进制代码,由操作系统管理。

三、代码示例

代码语言:javascript
复制
char * getP1(){
    char *p1 = "abcdef";
    return p1;
}
char * getP2(){
    char *p2 = "abcdef2";
    return p2;
}
int main(int argc, const char * argv[]) {
    char *p1 = getP1();
    char *p2 = getP2();
    printf("打印地址:%s,%s\n,",p1,p2);
    printf("打印内容:%d,%d\n",p1,p2);
    
    return 0;
}

打印的结果:

代码语言:javascript
复制
char * getP1(){
    char *p1 = "abcdef";
    return p1;
}
char * getP2(){
    char *p2 = "abcdef";
    return p2;
}
int main(int argc, const char * argv[]) {
    char *p1 = getP1();
    char *p2 = getP2();
    printf("打印地址:%s,%s\n,",p1,p2);
    printf("打印内容:%d,%d\n",p1,p2);
    
    return 0;
}

打印结果:

让人疑惑的是,为何在不同函数中声明的不变量,打印的会是同样的内容和地址。

在示例中的代码中,操作系统进入到main函数的入口,将变量p1,p2放入到栈中。p1和p2分别用来接收getP1()和getP2()函数返回的首地址,在64位机中,只占用内存的8个字节,在getP1()函数中,也有一个p1变量,因此把它放入到内存的栈中,把常量“abcdef”放入到全局区中。此时,函数getP1()中的p1指针是指向“abcdef”,假设该常量的值是“0xa11”,那就将这个地址赋给函数中的p1,函数的p1要将首地址放回给main函数中的p1变量。那么main函数中的p1也会指向上文中的首地址。这就是p1指针的内存解析说明。

在编译程序时,若编译器检测到全局区有两个同样的值,它就会代码进行优化,在内存中只保留一份。当这两个相同的值放置到全局区时,他会统一将这两个值合成一个,以避免造成内存空间的浪费。

所以,当编译器发现两个函数中变量的值相同之后,就将它们合二为一,p2指针按照上文中p1的分配方式对内存进行分配。到最后,就会发现p2指针与p1指针指向了相同的地址,且它们的内容也是相同的。这就是静态内存区域的全部解析。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.06.03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档