[C语言]内存管理

0x00 基本概念

内存管理,是指软件运行时对计算机内存资源的分配和使用技术。其目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。

内存分配方式:

  • 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在整个运行期间都存在。例如全局变量,static变量。
  • 从栈上创建。在执行函数时,函数内局部变量的存储变量都可以在栈上创建,函数执行结束时这些内存单元自动释放。栈内存分配运算内置于处理器的指令集中,效率很高,但分配的内容容量有限。
  • 从堆上分配,亦成为动态分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但需要处理的问题也多。

内存分区:

  • BBS段:未初始化的全局变量和静态变量。
  • 数据段:已初始化的全局变量和静态变量、字符串常量等。
  • 代码段:程序执行代码的一块内存区域。
  • 堆:动态分配的内存段。
  • 栈:存放程序临时创建的局部变量。

0x01 内存分配

为什么要进行动态内存分配?以数组元素为例,一个数组元素是存储于内存中连续的位置,当数组被声明时,其所需要的内存在编译的时候已经被分配。但在某些时候使用这种静态分配方式是不方便的,例如使用数组来存储班级中所有学生的成绩,但是不同的班级学生数量不同,这种情况下就无法确定数组到底分配多大内存。

常见动态内存分配、内存分配函数:

malloc

原型:extern void *malloc(unsigned int num_bytes);

头文件:stdlib.h

说明:在内存堆区分配一个大小为num_bytes的连续空间,如果分配内存成功,返回新分配内存的首地址,否则返回NULL。

用法实例:

int *p;

p = (int *)malloc(10*sizeof(int)); //分配4个字节的空间

calloc

原型:void *calloc(size_t n, size_t size);

头文件:stdlib.h

在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。

用法实例

int *p = (int *)calloc(10,sizeof(int));

realloc

用法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)

头文件:stdlib.h

说明:给已经存在的内存空间扩充大小

0x02 野指针

野指针指指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。——[百度百科]

野指针产生的主要原因:

  • 指针变量未初始化
  • 指针释放后未置空
  • 指针操作超过变量作用域

避免野指针的方法:

  • 初始化时置NULL
  • 释放时置NULL

0x03 内存泄露

内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。——[百度百科]

内存泄露分类(发生方式):

  • 常发性
  • 偶发性
  • 一次性
  • 隐式
int main()
{
	int *p = (int *)malloc(10 * sizeof(int));
	p = (int *)malloc(20 * sizeof(int));
	return 0;
}

以上代码很明显就会造成内存泄露,直接更改指针变量的指向,初始化时所分配的内存空间没有进行释放,它会随着程序的运行一直存在。

int main()
{
	int *p = (int *)malloc(10 * sizeof(int));
	free(p);                             //释放p所指向的内存空间
	p = (int *)malloc(20 * sizeof(int));
	return 0;
}

改成如下代码就不会发生内存泄露。如果p暂时不用重新指向其他空间,需要把p=NULL,不然会产生野指针。

0x04 总结

在动态分配内存的时候,需要养成编码习惯,尽可能的注意指针的指向,避免野指针、内存泄露的问题。

posted @ 2015-08-22 23:00  Wei丶Haijun  阅读(175)  评论(0编辑  收藏  举报