封装指针来监测指针是否被释放——曲线救渣

为什么会有 “监测指针是否被释放” 的需求?

	//声明一个int指针
	int *p1 = new int;
	//给指向的值赋值
	*p1 = 255;
	//声明一个int指针的数组,数组大小为1
	int**pArray = new int*[1];
	//把 p1 指针的值拷贝到 pArray[0]
	memmove(&pArray[0], &p1, sizeof(p1));
	//输出:address: 000001F49D79B1F0 value : 255,正常
	cout << "address: " << pArray[0] << " value: " << *pArray[0] << endl;
	if (p1 != nullptr) {
		delete p1;
		p1 = nullptr;
	}
	//输出:address: 000001F49D79B1F0 value: -572662307,可见内存已被释放
	cout << "address: " << pArray[0] << " value: " << *pArray[0] << endl;
	if (pArray[0] != nullptr) {
		//输出:"pArray[0] is not a nullptr,but can not be deleted!\n"
		cout << "pArray[0] is not a nullptr,but can not be deleted!\n";
	}

	delete pArray[0];//报错:

可见,如果指针的值从A处被拷贝到了B处,是不能通过 nullptr 来判断指针指向的内存释放被释放;如果访问了被释放的内存,一是结果不对,二是访问冲突。

当考虑使用boost的无锁队列时,如此声明 queue<int* > intPtrQueue; ,当push 的时候就是把指针的值拷贝到队列里了。

当然这个问题应该是智能指针能解决的问题,但是不会,所以先不用。

于是把指针封装一下:

class intPtr {
private:
	int* i_p;
	bool isUsing;
public:
	intPtr (int val) {
		Init(val);
	}
	void Init(int val) {
		i_p = new int;
		*i_p = val;
		isUsing = true;
	}
	void setVal(int val){
		*i_p = val;
	}
	void Delete() {
		if(i_p!= nullptr){
			delete i_p; 
			i_p= nullptr;
		}
		isUsing = false;
	}
	bool Using() {
		return isUsing;
	}
};

声明一个对象 intPtr *intptr = new intptr (255)
当需要释放 intptr 时,调用intptr->Delete() 释放内部申请的 int ,当别处需要使用 intptr 先判断intptr->Using()的真假,然后再做操作。

当最后需要释放所有intPtr 类型的对象时,先判断intptr->Using()的真假,真则先释放内部内存,再删除对象 ;假则直接删除对象。

总结一下:
1.intPtr 是一个壳子,里面装一个指针,壳子常在,而指针通过Init(int), Delete()发生改变;
2.指针可以是任意类型的指针;
3.在生产者和消费者模型中,特化为以下情形:
a.对n个生产者,声明n个壳子(intPtr),生产者把生成的数据的指针(本例是直接传int值)赋值给壳子,而同时生产者又拥有操作壳子的权利。操作时应该加锁 ;
b.壳子push到队列queue0,壳子中应有标志位表示壳子位于哪个队列,设为queue_id = 0;
c.消费者从queue1 pop,处理、展现、生成结果,把 queue_id = -1;
d.每个生产者通过判断 queue_id 来判断是否可以(需要)更新数据的指针所指向的数据,或释放之前的数据,来申请新的数据。
e.当生产者需要自己结束自己,或被用户要求结束时,调用Delete(),消费者可以得知壳中指针指向的内存已经不可访问,则在pop后释放壳子。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值