内容摘要:一些C++ 书上经常告诫程序员:要养成好的习惯,new 与 delete 要成对出现,时刻记住将内存释放回系统。但是,事情只是这么简单吗?
上面函数的原理就是:不停地删除那些灵巧指针不在CLockMarkArray所包含的指针中的指针,直到所有的指针的灵巧指针都存在于CLockMarkArray所包含的指针中。
所有被互锁的内存被找出来了,那么,下一步就是如何解锁的问题了。由此,我对灵巧指针引入了一个父类parent_autoptr 如下:
class parent_autoptr
{
public:
parent_autoptr()
{thisAutoMark=0;}
virtual ~parent_autoptr(){}
virtual void Release(){} file://释放指针的拥有权
protected:
int thisAutoMark; file://存放灵巧指针标志
};
在灵巧指针中,对函数 Release() 进行了重载。
template
class auto_ptr :public parent_autoptr
{
public:
virtual void Release(){Remove();}
auto_ptr()
{mark=0;pointee=0;thisAutoMark=GetAutoMark();}
auto_ptr(auto_ptr&rhs);
auto_ptr(T*ptr);
~auto_ptr(){Remove();}
T*operator->() const;
operator T*();
T&operator*()const;
auto_ptr&operator=(auto_ptr&rhs);
auto_ptr&operator=(T*ptr);
private:
void Remove();
int GetAutoMark();
CMutex *GetCMutex();
void ReadyWrite();
T*pointee;
int mark;
};
在 CMarkTable 和 CMark 中对互锁内存进行了释放,如下:
void CMarkTable::DoLockMark()
{
GetLockMark();
RemoveUnlockMark();
int size=CLockMarkArray.GetSize();
while(size)
{
CMark* theMark=(CMark*)CLockMarkArray[0];
CLockMarkArray.RemoveAt(0);
if(theMark)
{
int size2=(theMark->automarkArray).GetSize();
for(int i=0;i {
int automark=(theMark->automarkArray)[i];
RemoveGroup(automark);
}
theMark->Release();
}
size=CLockMarkArray.GetSize();
}
Init();
}
void CMark::Release()
{
int size=autoptrArray.GetSize();
for(int i=0;i {
parent_autoptr * thePtr=(parent_autoptr *)autoptrArray[i];
thePtr->Release();
}
}
到了现在,终于算是大功告成了,我马上把它投入测试当中,发现工作得非常好,即使开辟20至30个线程,程序也工作得很好,并没有抛出异常,而且垃圾回收的功能也非常好。但是,如果线程太多,那么在 CPtrManager 中为了保证线程同步,将会造成瓶颈效应,严重者将会严重影响执行效率。同时,如果每个线程都不停地产生死锁内存,那么,垃圾回收将应接不暇,时间长了,也会造成系统的资源耗尽。
代码的使用很简单,你只需要将我所附的两个文件加入到工程中,然后,在你的 C*App 中加入如下一段代码就行了:
CPtrManager thePtrManager;
这将保证 thePtrManager 在进程最后结束的时候才被析构。
如果你是在一个新的工程中使用,这就够了,但是,如果你还要使用原来的代码,特别是有指针参数的传递时,那么,你必须注意了。
如果需要从老代码中接收一个指针,而且这个指针需要你自己释放,那么可以使用灵巧指针,如果不需要释放,那么只能使用一般指针;
如果需要传递一个指针给老代码,而且这个指针需要你自己释放,那么可以使用灵巧指针,否则,只能使用一般指针。
责编:豆豆技术应用