A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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

8 个回复

倒序浏览
写得很好,见解独到。
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
了解内存区域能便于对于代码的理解,希望大家重视
回复 使用道具 举报
呉HENG 发表于 2017-6-10 21:45
了解内存区域能便于对于代码的理解,希望大家重视

其实细分的话是五大区域
回复 使用道具 举报
认真拜读,见解独到,代码规范,最后男神加油!
回复 使用道具 举报
还能说什么,除了66666666666666
回复 使用道具 举报
6666666666666666666666666
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马