背景略过...,检查代码,发现公司项目里某代码片段(为节省篇幅,片段经过重写,并以省略号代替部分次要函数的实现)如下:
template< class _Bty > class CUnknownImpl : public _Bty
{
public:
STDMETHOD( QueryInterface )(
_In_ REFIID iid,
_Deref_out_ void** ppvObject) throw()
{
...
}
STDMETHOD_( ULONG, AddRef )()
{
return InterlockedIncrement( &m_dwRef );
}
STDMETHOD_( ULONG, Release )()
{
DWORD dw = InterlockedDecrement( &m_dwRef );
if( !dw )
delete this;
return dw;
}
};
以上代码片段用以实现IUnknown接口。
以及这段:
__interface IErrorMessage : public IUnknown
{
virtual DWORD GetLastError() PURE;
virtual DWORD GetLastErrorMessage( __out_ecount_full_z( cchErrorMessageBufferSize ) LPWSTR lpErrorMessageBuffer,
__in DWORD cchErrorMessageBufferSize ) PURE;
};
class CErrorMessageImp : public CUnknownImpl < IErrorMessage >
{
public:
virtual ~CErrorMessageImp()
{
// 试图在析构函数中释放由HeapAlloc分配的内存(m_pszMessage )
ENSURE( HeapFree( GetProcessHeap(), IGNORE, m_pszMessage ) );
m_pszMessage = NULL;
m_cchMessageLength = 0;
}
virtual DWORD GetLastError()
{
...
}
virtual DWORD GetLastErrorMessage( __out_ecount_full_z( cchErrorMessageBufferSize ) LPWSTR lpErrorMessageBuffer,
__in DWORD cchErrorMessageBufferSize )
{
Copy m_pszMessage to lpErrorMessageBuffer ...
}
VOID SetMessage( LPCWSTR lpMessage )
{
m_pszMessage = HeapAlloc( ... );
Copy lpMessage to m_pszMessage;
}
private:
_Field_size_( m_cchMessageLength )WCHAR *m_pszMessage;
DWORD m_cchMessageLength;
};
这是我能看到,搜索到的绝大多数人,和贴子里对IUnknown接口的实现方法。没有虚析构函数!许多悲惨的程序员花费很大代价才学到这堂课 —— 《Effective STL》我指 “勿照抄代码” 和独立思考;