重学c语言系列三---变量在内存中的布局

时间:2021-12-19 14:55:02

 这次或许以后的东西不像写教科书那样,写板书来介绍所有的东西,我觉得那样不如直接给人推荐一本大师的c语言书就好了,我想吧自己学习过程中的思考过程记录下来,不仅仅是阐述结果,而是结果是怎么来的,当然这么写,很可能随着思路不知道扯到哪里,显的逻辑性不强。但是我还是想记录下自己的学习方法或者思维方法。  另外我觉得关于内存这一块牵扯的比较多,可能一次讲不完,我会继续补充的。

       扯了这么多,其实我想知道的是编程使用变量,它在内存中如何存储?

      为了弄明白这一点,我们先来看看整个内存大致是如何分布的,事先声明,以下举例或者说明皆在linux 32位操作系统,4G内存的环境下,如果你用自己环境尝试和我说的结果不同欢迎讨论。如何知道内存是如何分布的?我选择的方法是百度,所采用的资料在文章结尾都有链接,不保证在将来是否失效,如果觉的相关部分我说的不够清楚,请自行参阅,欢迎学有所成后提供建议。

     先粗略的看,内存分为用户模式空间和内核空间,如下图:

重学c语言系列三---变量在内存中的布局

 再详细一点划分如下:

 重学c语言系列三---变量在内存中的布局

一步跳到这里确实有点突兀,一般的介绍应该都是只讲堆,栈,数据段,代码段

稍微解释一下,栈中所存放的数据是局部变量,堆(heap)中存放的是动态分配的内存,(malloc/free,new/delete.....)所分配的内存

bss("block started by symbol"的缩写,意味符号开始的块)存放的是未初始化的全局变量和静态变量,该段变量只有大小,名称,却没有值,是编译器处理

        未初始化数据的地方,一般在程序一开始就会被清零,由于bss段只保存没有值的变量,所以事实上它不需要保存这些变量的映像,运行时所需要的bss段大小记录

        在目标文件中,但bss段(不像其它段)并不占据目标文件的任何空间.

data存放的是已经初始化的全局变量和静态变量

text段存放的是二进制代码。

    和预想中整整齐齐一块接一块的区域不同,各个内存区域之间有着随机偏移值,为什么要弄这个东西?不是增加了内存碎片?

    为了弄明白这个东西,我们来试试简单的缓冲区溢出,拿栈做例子,代码如下:

#include<stdio.h>
#include<string.h>

int main()
{
      char str[4];
      int access;
      
      while(1 ){
      	 access=0;
      	 scanf("%s",str);
      	 if(strcmp(str,"1234")==0)
      	 	access=1;
      	 if(access!=0)
      	 printf("Welcome to new world!\n");
      	 else
      	 printf("wrong key,please input again\n");
      	 
      }	
      
}
测试结果如下:

重学c语言系列三---变量在内存中的布局

为什么会是这样?

因为只分配了4个字节给str,  str和access在内存中布局如下:

重学c语言系列三---变量在内存中的布局

   也许你会疑问,为什么access在内存中的地址会在str上面,根据上面整个内存的图,栈中分配方向是从高到低,而在main函数栈帧中,根据代码,str应该先分配

才是,我开始也有这个疑问,还准备去*去提问,不过在segmentfault中找到了答案,中文的答案看上去要亲切一些,解释如下:

局部变量的空间不是一个一个压入栈中的,而是一次性分配好的,所以理解为变量依次入栈是错误的。C语言也没有规定局部变量在内存中的位置,只是常常实现为先定义的变量在高地址、后定义的变量在低地址。不过局部变量在栈上的位置没有绝对的关系,甚至不一定会出现在栈上

 这样,因为字符串函数只是根据\0,来判断结束,很容易造成溢出的情况,导致程序bug

 发现写了这么多,好像和主题关系不是那么明确,决定下篇博文继续这个主题,好好写,而当务之急是把这个收尾,缓冲区溢出是问题很严重的,而各个段起始地址加上随机

 偏移之后会让缓冲区溢出变的更加困难,我在后续的文章中会专门讨论这个,这里就简单pass,接下来真正见识变量在内存中的布局吧

                                                                           




参考链接(资料):

剖析程序的内存布局

Bss段解释

《c专家编程》