C/C++内存管理简析

最近,在一次面试中偶然被问及内存管理的问题,虽然之前在好多书中有所看到,但真正在经过一番思考和回答时发现还是有些哞乱和模糊,于是,就简单的进行描述;

       首先,就操作系统方面来讲,内存管理的功能就是为多道程序的运行提供良好的环境,方便用户使用内存,提高内存的利用率以及能从逻辑上扩充内存;因此,内存管理具有以下功能:内存分配、内存保护、地址映射、内存扩充

 内存分配:采用静态和动态两种分配方式;

        静态内存分配中,每个作业的内存空间在装入是就确定,而在程序集作业的运行过程不允许在申请申请新的内存空间;而在动态聂存分配方式中,每个作业所要求的基本内存空间也在装入是确定,但允许在运行过程动态申请附加的内存空间;

内存保护:确保每到程序在自己的额内存空间执行;不允许访问OS的程序和数据;也不允许用户程序转移到非共享的其它程序中执行;通常,有内存保护机制设置两个界限寄存器,分别放在正执行程序的上届和下届,而越界检查有硬件完成;

地址映射:多道程序环境下,运行程序地址空间内的逻辑地址和物理地址不相一致,这就必须借助地址映射机制,将逻辑地址转换为内存空间中与之对应的物理地址;

 内存扩充:借助于虚拟存储技术,实现逻辑上的内存扩充,而并非去扩大物理内存容量

那么,在C/C++中的内存管理又是怎样呢

         在C/C++中,内存大体分成5个区,他们分别是栈、堆、全局/静态存储区、常量区、代码区

  栈,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

  堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。 它和由malloc等分配的内存块十分相似,不过malloc是用free来结束自己的生命的。 

  全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。 

  常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量不允许修改。

       代码区:存放整个程序的代码,数据和代码是分开存储的;

比如:

void f()

 {     int* p=new int[5] ;   }  

      //在栈内存中存放了一个指向一块堆内存的指针p。程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中.

注意:

malloc申请的是连续的一块内存,当返回NULL表示内存申请失败。

if(p == NULL)

{

      exit(1);   // 终止整个程序; 栈出现内存泄露情况通常是由没有回收垃圾资源,没有进行内存释放引起的

}


 free(p);斩断了指针与这块内存的关系,

     虽然指针P仍然保存原来的地址,但是已经失去了对那块内存的控制权,同样,对应的那块内存虽然内容存在,不过,已经无法利用其中的数据,成为垃圾文件对于每次malloc()只能有一次free(),free()两次会出错,除非原指针指向NULL;

测试程序:

  1. #include <stdio.h>
  2. static int x;    //全局静态变量
  3. char ar[2];      //全局普通变量(静态区)
  4. char *s = "abcdef";  //常量区

  5. void fun(int i)  
  6. {  
  7.     int j = i;  
  8.     static int a = 100;  
  9.     static int  b;  
  10.   
  11.     printf("子函数的参数:        0x%p = %d\n", &i, i);  
  12.     printf("子函数 栈中数据地址: 0x%p = %d\n", &j, j);  
  13.     printf("子函数 静态数据地址(有初值): 0x%p = %d\n", &a, a);  
  14.     printf("子函数 静态数据地址(无初值): 0x%p = %d\n", &b, b);  
  15.  
  16. int main()  
  17. {  
  18.     int i = 5;  
  19.     static int a = 100;  
  20.     static int b;
     
  21.      
  22.    printf("全局静态变量地址:0x%p\n", x);
  23.    printf("全局普通变量地址:0x%p\n",ar[0]);
  24.    printf("常量地址:0x%p\n",s);
  1.     printf("主函数 栈中数据地址: 0x%p = %d\n", &i, i);
  2.     printf("主函数 静态数据地址(有初值): 0x%p = %d\n", &a, a);  
  3.     printf("子函数 静态数据地址(无初值): 0x%p = %d\n", &b, b);  
  4.     putchar('\n');  
  5.   
  6.     fun(i);  
  7.     return 0;  
  8. }  

全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的?

生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁;局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在;内存中分配在全局数据区。

使用方式不同:通过声明后全局变量程序的各个部分都可以用到;局部变量只能在局部使用;分配在栈区。
操作系统和编译器通过内存分配的位置来知道的,

全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值