一、内存分配方式
内存分配方式有三种:
1、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,例如全局变量,static变量。
2、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放,栈内存分配运算内置于处理器的指令集中,效率很高,凡是分配的内存容量有限。
3、从堆上分配。也称动态内存分配。程序在运行的时候用malloc或者new申请任意多少的内存,程序员自己负责在何时用free或者delete释放内存。动态内存的生存期有程序员决定,使用非常灵活,但如果在堆上分配了空间,就有责任回收他。否则运行的程序会出现内存泄漏,频繁的分配和释放不同大小的堆空间将会产生堆内碎块。
二、程序的内存空间
一个由C/C++编译的程序占用的内存分为以下几个部分:
1、栈区(stack)-- 由编译器自动分配释放,存放为运行函数而分配的局部变量,函数参数,返回数据,返回地址等。
2、堆区(heap)-- 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。分配方式类似于链表。
3、全局区(静态区)(static)-- 存放全局变量、静态数据、常量。程序结束后由系统释放。
4、文字常量区--常量字符串就是放在这里的。程序结束后由系统释放。
5、程序代码区 -- 存放函数体(类成员函数和全局函数)的二进制代码。
三、常见的C语言内存错误及对策
1、指针没有指向一块合法的内存
定义了指针变量,但是没有为指针分配内存,即指针没有指向一块合法的内存,常见以下几种情况
(1)结构体成员指针未初始化
(2)没有为结构体指针分配足够的内存
(3)函数的入口校验
2、为地址分配的内存太小
为指针分配了内存,但是内存大小不够,导致出现越界错误
3、内存分配成功,但并未初始化
定义一个变量时,第一件事就是初始化,在定义变量和数组时也可以初始化
4、内存越界
内存分配成功,且已经初始化,但是操作越过了内存的边界。这种错误经常是与由于操作数组或指针时出现“多1”或“少1”的情况
5、内存泄漏
(1)使用malloc函数,如:char *p = (char *)malloc(sizeof(指向的数据类型)*100);
(2)使用malloc函数要检查内存是否申请成功,if(NULL != p)语句来验证;
(3)用malloc函数申请0字节指针时 if(NULL != p)语句校验将不起作用
(4)内存释放;使用malloc函数需要用free函数释放该内存块的首地址、使用malloc函数和free函数要对影响等否则发生段错误!
(5)内存释放之后:使用函数free之后指针变量本身保存的地址并没有改变,需要从新把p的值变为NULL;
p = NULL;
如果没有将指针置为NULL,这个指针就变为“野指针”。所以,free之后,一定要给指针置为NULL
6、内存已经释放,但是继续通过指针来使用
这里一般由三种情况:
(1)就是之前所说的,free(p)之后,继续通过p指针来访问内存,解决的办法就是给p置为NULL
(2)函数返回栈内存。比如在函数内部定义一个数组,却用return 语句返回质量该数组的指针。解决的办法就是弄明白栈上变量的生命周期。
(3)内存使用他太复杂,弄不清楚到底那块内存被释放,那块没有释放。解决的办法就是重新设计程序,改善对象之间的调用关系。
最后,希望大家尽量使自己对每种错误发生及预防的手段烂熟于心,多练,多调试代码,多总结经验。