正确使用内存

对于初学者来说,内存是个神秘的空间,程序的绝大部分错误也是由于内存使用不当造成的,而且这些错误往往都是隐藏很深的。因此,如何掌握内存的使用,通晓系统对内存的管理手段,将是软件成功的一个关键因素。

首先我们先了解内存的分配方式。一般来说,内存的分配有三种方式:

1、从静态存储区域分配:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

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

3、从堆上分配,亦称动态内存分配:程序在运行的时候用malloc或new申请任意大小的内存,程序员自己赋值在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

以上三种分配方式的内存生存周期:

1、静态分配的区域的生存周期是整个软件运行期间,就是说从软件运行开始到软件终止退出。只有当软件终止运行后,这块内存才会被系统回收。

2、在栈中分配的内存生存周期与这个变量所在的函数和类有关。如果是函数中定义的局部变量,那么它的生命期就是函数被调用时,当函数运行结束,那么这块内存会被回收。如果是类中的成员变量,则它的生命期与类实例的生命期相同。

3、在堆中分配的内存,生命期是从调用malloc或new开始,到调用free或delete结束。如果不调用free或delete,则这块内存会在软件结束运行后才会被系统回收。

下面我们再看看在使用内存过程中我们经常会引发什么样的错误,以及我们应该采取什么措施。

常见错误及对策:

1、内存分配未成功,却使用了它。

编程新手经常会犯这样的错误,因为他们没有意识到内存分配会不成功。常用的解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果用malloc或new申请的内存,用if(p!=NULL)或if(p==NULL)来进行防错处理。

2、内存分配虽然成功,但是未初始化就用它。

犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省值为0,导致引用初值错误(如数组)。

内存的初始值是多少并没有统一的标准,尽管有些时候为0,我们宁可信其有,不可信其无。所以无论以何种方式创建数组,都别忘了赋初值,即使是赋0也不能省略,不要嫌麻烦。

3、内存分配成功并且已经初始化,但操作越界。

例如在使用数组时经常发生下标“多1”或“少1”。特别是在for循环语句中,循环次数很容易搞错,导致数组越界。

4、忘记释放内存,造成内存泄露。

含有这种错误的函数每被调用一次就丢失一块内存。刚开始内存充足看不到错误,终有一次会程序会突然死掉,并出现提示:内存耗尽。

动态内存的申请与释放必须配对。程序中malloc与free一定要次数一致,否则会出现错误(new和delete也一样)。

5、释放了内存却继续使用它。

有三种情况:

(1)、程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放内存,此时应该重新设计数据结构,从根本上解决对象管理混乱的局面。

(2)、函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。

(3)、使用free或delete释放内存后,没有将指针设置为NULL,导致产生“野指针”。

综上所述,我们应该注意:

1、使用malloc或new申请内存之后,应该立即检查指针是否为NULL,防止使用指针值为NULL的内存。

2、不要忘记为数组和动态内存赋初值,防止将未被初始化的内存做右值使用。

3、避免数组或指针的下标越界。

4、动态内存的new与delete应成对出现,防止内存泄露。

5、使用free或delete释放内存后,及时将指针设置为NULL,防止产生“野指针”。

下面举几个经典的错误例子,大家不要犯相同的错误:

1、返回栈内存指针

char* GetString()

{

char* p="hello world";

return p;

}

char* pGet=GetString();

这段程序编译和运行都没有问题,但你却无法使得返回的pGet指针指向你想要的“hello world”,因为指针p是生命周期在函数GetString内,运行完函数GetString()后,p分配的栈内存马上就被系统回收了,虽然pGet指向了pl当初分配的内存地址,但那块地址已经没有内容了。

2、这是一个出现频率非常高的错误例子

cahr* p=new char;

...

int a;

p=&a;

...

delete p;

这段程序有两个问题:一是p=&a;将导致p原先分配的内存无法再被获取,就像我们丢失了朋友的电话号码一样,我们再也联系不到这个朋友了。这就造成了内存泄露。如果内存泄露的多了,可能导致系统的崩溃,因为可用的资源越来越少,直到枯竭。二是delete p;将导致异常发生,因为这时的p指向的已经不是动态分配的内存了,而是指向了a分配的栈内存,而栈内存是不能使用delete来回收的,因此将导致异常。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值