又见悬空指针

103 篇文章 0 订阅
33 篇文章 0 订阅

概念

悬空指针:顾名思义,其指向的内存已经被释放,但是指针使用者并不知道,通过指针访问了非法内存,结果随机。悬空指针常发生在指针浅拷贝场景,根本原因是信息不同步问题。


实际场景

最近对引擎做一次比较大升级,结果还是引入了一些隐晦BUG,本文着重还原一个悬空指针的场景示例代码如下:

class StyleMgr { 
public:
	StyleMgr(): _default(NULL), pStyleArr(NULL)	{ /* .. 其他初始化 ..*/ } 
	
	//... 析构 ...
	
	int Create(const char* file, int index) {
		Clear();
		
		_pStyleArr = new Style[];
		// ... parse from file...
	}
	
	void Clear() {
		_hashTb.removeAllObject();
		delete [] _pStyleArr;
		_pStyleArr = NULL;
	}
	
	Style* GetStyle(int id) {
		if (!_default) {
			_default = _hashTb.find(DEFAULT_CODE);
		}
		
		if (!_hashTb.has_contains(id)) {
			return _default;
		}
		return _hashTb.find(id);
	}
	
private:
	Style*		_pStyleArr;	
	HashTable 	_hashTb;	
	Style* 		_default;
};
StyleMgr内部_pStyleArr是样式数组,存储所有style指针,_hashTb为样式哈希表为了快速查找,_default为查找失败的默认样式。 _default, _hashTb都与_pStyleArr共享内部指针。

悬空指针出错的场景:

StyleMgr smgr = new StyleMgr();
// 1.首次创建...
smgr.Create("style.dat", 0);

// 2.获取样式...
style1 = smgr.GetStyle(id1);
style2 = smgr.GetStyle(id2);

// 3.其他地方再次创建
smgr.Create("style.dat", 1);

// 4.悬空指针出场:
style3 = smgr.GetStyle(bad_ID);		
注意上面4段代码都不在一个地方

第二段代码调用GetStyle以后此时_default指向了首次Create时_pStyleArr内部的同时也是_hashTb内部的一个样式。

第三段代码再次调用Create函数,此时Create内部调用Clear以后,重建了_pStyleArr_hashTb结构,此时_default仍然不为空,持有已经释放的内存地址。

第四段代码再次调用GetStyle时候,如果传入的是合法ID,结果OK!但是当传入非法ID,将_default返回,结果就随机了。。。

原因分析:coding的时候没意识到Create函数会多次重入,Clear函数本意是将整个StyleMgr成员状态重置,忘记处理_default。于是当Create、GetStyle、Create、GetStyle组合调用时,最后一次的GetStyle引入了悬空指针隐患,多次重入取到的默认样式可能随机。


后话

巨大的一个工程中,而且涉及不同地方调用,指望CV很难发现问题。通过gflags也没发现问题,因为只有查找失败时才返回default样式,而且返回后还不一定出错。

这个BUG是代码提交十天后才发现,当时跟踪另外一个bug,调试的时候偶然发现_default指向内容为空。。。然后就查啊查啊查。。。

查到问题改起来十分容易啦~

指针问题没有小问题,对待指针问题一定小心又小心。。。

-  20140405 dizuo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值