ASSERT
#ifndef ATLASSERT #define ATLASSERT(expr) _ASSERTE(expr) #endif
上述这个宏依赖CRT
传输到debug output
inline void _cdecl AtlTrace(LPCSTR pszFormat, ...) inline void _cdecl AtlTrace(LPCWSTR pszFormat, ...)
例子:
HRESULT CPenguin::FinalConstruct() {
ATLTRACE(__TEXT("%d+%d= %d\n"), 2, 2, 2+2);
}
还可以提示级别:
void AtlTrace2(DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFormat, ...) void AtlTrace2(DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFormat, ...)
在ATL内部已经制定了一套Category
#ifdef _DEBUG #define DECLARE_TRACE_CATEGORY( name ) \ extern ATL::CTraceCategory name; #else #define DECLARE_TRACE_CATEGORY( name ) const DWORD_PTR name = 0; #endif DECLARE_TRACE_CATEGORY( atlTraceGeneral ) DECLARE_TRACE_CATEGORY( atlTraceCOM ) DECLARE_TRACE_CATEGORY( atlTraceQI ) DECLARE_TRACE_CATEGORY( atlTraceRegistrar ) DECLARE_TRACE_CATEGORY( atlTraceRefcount ) DECLARE_TRACE_CATEGORY( atlTraceWindowing ) DECLARE_TRACE_CATEGORY( atlTraceControls ) DECLARE_TRACE_CATEGORY( atlTraceHosting ) DECLARE_TRACE_CATEGORY( atlTraceDBClient ) DECLARE_TRACE_CATEGORY( atlTraceDBProvider ) DECLARE_TRACE_CATEGORY( atlTraceSnapin ) DECLARE_TRACE_CATEGORY( atlTraceNotImpl ) DECLARE_TRACE_CATEGORY( atlTraceAllocation ) DECLARE_TRACE_CATEGORY( atlTraceException ) DECLARE_TRACE_CATEGORY( atlTraceTime ) DECLARE_TRACE_CATEGORY( atlTraceCache ) DECLARE_TRACE_CATEGORY( atlTraceStencil ) DECLARE_TRACE_CATEGORY( atlTraceString ) DECLARE_TRACE_CATEGORY( atlTraceMap ) DECLARE_TRACE_CATEGORY( atlTraceUtil ) DECLARE_TRACE_CATEGORY( atlTraceSecurity ) DECLARE_TRACE_CATEGORY( atlTraceSync ) DECLARE_TRACE_CATEGORY( atlTraceISAPI ) // atlTraceUser categories are no longer needed. // Just declare your own trace category using CTraceCategory. DECLARE_TRACE_CATEGORY( atlTraceUser ) DECLARE_TRACE_CATEGORY( atlTraceUser2 ) DECLARE_TRACE_CATEGORY( atlTraceUser3 ) DECLARE_TRACE_CATEGORY( atlTraceUser4 ) #pragma deprecated( atlTraceUser ) #pragma deprecated( atlTraceUser2 ) #pragma deprecated( atlTraceUser3 ) #pragma deprecated( atlTraceUser4 )
用户可以这样使用:
CTraceCategory PenguinTraces( "CPenguin trace", 1 ); ... STDMETHODIMP CPenguin::Fly() { ATLTRACE2(PenguinTraces, 2, _T("IBird::Fly\n")); ATLTRACE2(PenguinTraces, 42, _T("Hmmm... Penguins can't fly...\n")); ATLTRACE2(atlTraceNotImpl, 0, _T("IBird::Fly not implemented!\n")); return E_NOTIMPL; }
当然还有更简便的方法,因为ATL已经有了:
#define ATLTRACENOTIMPL(funcname) \ ATLTRACE2(atlTraceNotImpl, 2, \ _T("ATL: %s not implemented.\n"), funcname); \ return E_NOTIMPL
所以:
STDMETHOD(SetMoniker)(DWORD, IMoniker*) { ATLTRACENOTIMPL(_T("IOleObjectImpl::SetMoniker")); }
Tracing Calls to QueryInterface
在编译时指定_ATL_DEBUG_QI,则可以跟踪QueryInterface
Tracing Calls to AddRef and Release
在编译时指定_ATL_DEBUG_INTERFACES,则可以跟踪QueryInterface,AddRef,Release,并且可以检验是否有LEAK
使用_AtlDebugInterfacesModule可以指定break,例如:
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { hInstance; BOOL b = _AtlModule.DllMain(dwReason, lpReserved); // Trace down interface leaks #ifdef _ATL_DEBUG_INTERFACES _AtlDebugInterfacesModule.m_nIndexBreakAt = 4; #endif return b; }
_ATL_DEBUG_REFCOUNT
对于ATL3之前的版本,等效于_ATL_DEBUG_INTERFACES