今天对代码进行了一些重构。主要变化是原来直接使用一个双向链表模板类实例化一个具体的叶子类CWork。这个时候工作得很好。
主要的函数如下:
//释放结点对象
//若m_bNestingDelete,一并释放结点叶子 对象
static void ReleaseItem(CListNode<_type>* obj)
{
if (NULL == obj)
return;
else
{
if (obj->pre == obj || obj->next == obj )
{
if (NULL != obj->m_pLeaf)
{
if ( m_bNestingDelete )
delete obj->m_pLeaf;
delete obj;
}
else
{
delete obj;
obj = 0;
}
return ;
}
else
{
CListNode<_type>* tempNext = obj->next;
CListNode<_type>* tempPre = obj->pre;
if ( m_bNestingDelete )
if ( obj->m_pLeaf != NULL)
delete obj->m_pLeaf;
delete obj;
tempNext->pre = tempPre;
tempPre->next = tempNext;
return;
}
}
}
主要的数据域成员:
CListNode<_type> * pre;
CListNode<_type> * next;
_type* m_pLeaf;
后来加了一个间接类:CWorkQueue,则通过这个类获取CListNode,进而进行对具体的CWork类的操作。
这个时候,可怕的问题出现了,原来工作的好好的ReleaseItem函数的delete obj->m_pLeaf语句居然在dbgheap.c的
/* Error if freeing incorrect memory type */
_ASSERTE(pHead->nBlockUse == nBlockUse);
这样一句断言失败。此时nBlockUse的值是C00004,而正常情形下均为1。STL的模板类中从而没有包含具体的应用类但是应用
此时应用CListNode实例化别的类后ReleaseItem,好好的!
这时我们怀疑问题出在了CWorkQueue上,CWorkQueue.h中声明了class CWork;而在其cpp中才进行了文件包含。
试着把CWork头文件直接包含在了CWorkQueue.h中,运行后断言不再失败。
由此,我们知道应该是类型的问题。
通过查看调用处发现,该清除动作由CWorkQueue返回的CWork指针调用CWork类中新加的显式调用CListNode的static的ReleaseItem方法完成。
而CWorkQueue的返回函数正是在.h中所写的一个内联函数,由此,我们怀疑CWork的类类型在ReleaseItem动作执行时,具体来讲,就是delete动作
执行时,还并不明确。为证明此观点,还原CWork.h在CWorkQueue.h中的#include位置,并将该内联函数放到.cpp中写定义。这个时候重新执行,
好吧问题仍然如故。经过review,发现问题出在了CWorkQueue中的数据成员CListNode<CWork> m_DblistNode上。。。。。。。天才。。。
那么结论就是:
如果你要用模板类,那么尽量地用指针,如果你不喜欢用指针,那么尽量地保持只在两个.h间发生模板关系------类类型在多个.h间不具有传递效果。