专栏首页谦谦君子修罗刀静态内存区域解析

静态内存区域解析

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

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

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

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

三、代码示例

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;
}

打印的结果:

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指针指向了相同的地址,且它们的内容也是相同的。这就是静态内存区域的全部解析。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 程序员面试闪充 -- 性能优化

    CPU 和GPU 关于绘图和动画有两种处理方式CPU(中央处理器)和GPU(图形处理器),CPU的工作都在软件层面,而GPU的在硬件层面。 总的来说,可以使用...

    谦谦君子修罗刀
  • swift手撕二维码一、简介二、二维码综合案例

    超市付款扫一扫,免费wifi扫一扫,添加好友扫一扫。 二维码就像是神一般的存在!! 可是到底二维码是个啥呢? ? QRCode.jpg 一、简介 1、概念 ...

    谦谦君子修罗刀
  • React Native备课笔记Day01一、React Native介绍二、特点分析三、推荐网站以及运行第一个react native项目四、环境搭建五、React Native文件结构六、View

    (本节包括React Native介绍、特点分析、环境搭建、RN文件结构、View组件讲解、FlexBox布局及props与state) 一、React Nat...

    谦谦君子修罗刀
  • HDUOJ--------(1198)Farm Irrigation

    Farm Irrigation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32...

    Gxjun
  • 单片机的存储区范例

    用户4645519
  • 常量字符串和指针

    为了节省内存,C++把常量字符串单独放在一个内存区域,如果有几个指针指向相同的常量字符串时,它们实际上指向的是相同的内存地址。 而数组是要每一个数组单独占用一块...

    用户1215536
  • OpenAI推新程序包:GPU适应十倍大模型仅需增加20%训练时间

    安妮 编译自 Medium 量子位 出品 | 公众号 QbitAI GPU内存太小可能是神经网络训练过程中最大的拦路虎。 不怕,用这个OpenAI推出的grad...

    量子位
  • 堆和栈的区别

    一、预备知识—程序的内存分配          一个由C/C++编译的程序占用的内存分为以下几个部分     1、栈区(stack)— 由编译器自动分配释放,存...

    互联网金融打杂
  • 「c/c++专业知识讲解」超详细讲解栈和堆的区别!

    1、栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其

    诸葛青云
  • Python面向对象编程基础

    面向对象编程是Python中的核心之一,面向对象的核心并不是概念,语法,使用有多么复杂,而是一种编程思想,并不是掌握了类创建与使用就真正掌握了面向对象编程,这需...

    py3study

扫码关注云+社区

领取腾讯云代金券