内存陷阱 驯服C 中的野指针
2008-02-23 05:27:20来源:互联网 阅读 ()
一个母亲有两个小孩(两个指针),一个在厨房,一个在卧室,(属于不同的代码块,其生存期不同)母亲让在厨房的小孩带一块蛋糕(指针指向的对象)给在卧室的小孩,这样在卧室的孩子才肯写作业。但这个在厨房的小孩比较淘气,他在走出厨房时自己将蛋糕吃了,没能带出来。而在卧室的没有吃到蛋糕,所以不肯完成他的作业。结果母亲却不知道卧室的孩子没有吃到蛋糕,还以为作业完了。结果第二天她就被老师召唤到办公室了。事情麻烦了。
这样,那个在卧室的孩子就是野指针了,因为他没有得到应得的蛋糕,不能完成母亲交给他的作业。
这就是c中所讲的野指针。上面的小剧本但是演示了一种最基本的野指针的形成过程。更容易出现的情形是coder在编码时,大意之下使用了已free过的指针。
对于年轻点的经验欠缺的coder来说是比较容易犯的错误,经验老到的程式员或慎重采取成对编程的形式避免这种失误,或使用引用计数器防止形成野指针。
总之,在c中,野指针也许性子野,但是控制起来也是有章可循。然而事情在c 中出现了变化。
coder们面临更大的麻烦了。c 程式员无可避免的要写很多这样那样的类。谁让c 是面向对象的呢?
我们在写类的时候难免要用new给类的数据成员分配内存。这本来没什么,动态分配内存是一种很常见的基本操作,我们在学数据结构时经常这么做,不是么?
但是伙计,事情并非这么简单。类是一种高级的用户自定义数据类型,看起来和结构、枚举这样的用户自定义类型没啥太大差别。假如您这样认为....?那您会死的很惨。类太复杂了,普通情况下使用类的对象并没有太大的问题,但是,当您要复制一个对象时,问题就来了。
比如我们知道,您要用一个对象初始化另一个对象时,c 是按位进行拷贝的,即在目标对象里创建了初始化对象的一个完全相同的拷贝。这在多数情况下已足够了。但是,当您的类在创建时为每个对象分配内存,也就是说类中有new操作。当您的对象创建好后,类也为对象分配了一块内存。假如您用这个对象去初始化另一个对象时,被初始化的对象和初始化的对象完全相同。这意味着,他们使用同一块内存,而不是重新为被初始化的对象分配内存。
这样麻烦就大了。假如一个对象销毁了,那么分配的内存也就销毁了(别忘了,类是有析构函数的,他负责在对象销毁时,释放动态分配的内存。难道您说您不在类中写上析构部分?那么可怜的孩子,那您就走向了另一个深渊,当您的程式运行数小时之后,系统会告诉您,内存不够用了。想象一下把您的程式用在腾讯的服务器上),另一个对象就残缺不全了,这就像一对连体婴儿,他们共用了一部分器官,心脏或肝脏。要救活一个,就牺牲了另一个。一个得病了,另一个也要遭殃。
能够说,这就是c 中更加变态的野指针。
什么?您说我不用对象初始化对象?那么我们会不会将一个对象作为变元传递给函数呢?我们很多时候都这样做。有时我们不得不将对象按值传递给一个函数,但是您要知道,按值传递是什么意思?他的意思就是,把实参的一个拷贝传递给函数。这和刚才的初始化没什么两样,按位拷贝,函数体内的对象和外面的对象共用一块内存,即便在函数中的对象没有对这块内存进行过操作,但是当函数结束时。。。。析构函数将会被调用......
更有一种和之相反的情况......, 当您想要把一个在函数内的对象值返回给外面的对象时,这时候,会自动产生一个临时对象,由他容纳函数的返回值,并在函数结束时把结果传给目标。那么这个临时对象迅速的被创建,并被迅速的释放。。。一块内存被释放了两次。其后果是不可预见的。
当您把一个对象的值赋给另一个对象时,假如您没有重载赋值运算符,那么也会导致按位拷贝。最终产生一个野指针(一个隐藏在类内的毒瘤),或释放同一块内存多次。
看到了么?害怕了么?是不是感到C 到处都是陷阱呢?不但有陷阱,到处都是危险品。任何c中的疑难问题,到了c 就成了一般问题了。好了不废话了,我们继续讲讲解决之道。
对于最后的这种赋值的情况,我们只有通过重载赋值运算符才能解决,也就是避免按位拷贝。
至于前面的都属于初始化,概括下来就是三种情况:
1.当一个对象初始化另一个对象时,例如在声明中;
2.把所创建的对象拷贝(按值)传递给一个函数时;
3.生成临时对象时,最常见的就是函数的返回值。
解决初始化时的按位拷贝问题,我们通过创建拷贝构造函数来解决。
基本的拷贝构造函数形式为:
classname (const classname &o)
{
//body here
}
拷贝构造函数就是针对这个问题而设计的。
恩,大家都明白了吧?不要让您的对象都变成可怜的连体人啊~~~~
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇: 一个经典RPG游戏
下一篇: 浅谈C/C 内存泄漏及其检测工具
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash