COM_INTERFACE_ENTRY_BREAK macros doesn't work - c++

I have an ATL class. I'd like to know when QueryInterface of this class is called in order to remove memory leaks.
I added COM_INTERFACE_ENTRY_BREAK's in the COM_MAP, now it looks like:
BEGIN_COM_MAP( CMyClass )
COM_INTERFACE_ENTRY( IFace1 )
COM_INTERFACE_ENTRY( IFace2 )
//COM_INTERFACE_ENTRY_BREAK(IUnknown) // i included this too
COM_INTERFACE_ENTRY_BREAK( IFace1 )
COM_INTERFACE_ENTRY_BREAK( IFace2 )
END_COM_MAP()
When i start to debug (pressing F5) i have no breakpoint after the QI operation. I'm sure that QI is called because _ATL_DEBUG_INTERFACES shows a leak in the output window
ATL: QIThunk - 4 LEAK : Object = 0x02150CC0 Refcount = 1 MaxRefCount = 2 CMyClass - IUnknown
What should I do in order to have a breakpoint stopped at QI calling?
Thank you.

Clearly you want a breakpoint on the AddRef() call, not the QI call. Yes, painful, finding reference counting bugs in the client code from the server doesn't work very well if you use the ATL wrappers. Not otherwise fundamentally different from trying to diagnose memory leaks by setting a breakpoint on the new/delete operators, that doesn't work well either.
You can set a breakpoint on the InternalAddRef() method inside atlcom.h. But it can be noisy and it may cause the debugger to go catatonic for a while if you have a lot of interfaces in your server.

I've solved the problem with COM_INTERFACE_ENTRY_FUNC_BLIND macro like this:
BEGIN_COM_MAP(CMyClass)
COM_INTERFACE_ENTRY(IDummy) // NB!: this has to go before COM_INTERFACE_ENTRY_FUNC_BLIND
COM_INTERFACE_ENTRY_FUNC_BLIND(0, MyQueryInterface)
END_COM_MAP
MyQueryInterface is a function called every time an interface is querying.
My function is:
QueryInterfaceFunc ( void* pv, REFIID riid, LPVOID* ppv, DWORD dw )
{
if (riid == __uuidof(IFace1))
{
DebugBreak(); // Break here in the case of querying IFace1
}
}

Related

CreateThread inside another thread

I am having an issue creating a thread inside of another thread. Normally I would be able to do this, but the reason for this issue is because I've Incremented Reference Count of the DLL which starts these threads. I need to start multiple threads inside this DLL. How can I get around this and be able to issue multiple CreateThread()'s when needed in my project without experiencing problems because of the Incremented Reference Count in my DLL?
Here is the function I've written to Increment Reference Count in my DLL file:
BOOL IncrementReference( HMODULE hModule )
{
if ( hModule == NULL )
return FALSE;
TCHAR ModulePath[ MAX_PATH + 1 ];
if ( GetModuleFileName( hModule , ModulePath , MAX_PATH ) == 0 )
return FALSE;
if ( LoadLibrary( ModulePath ) == NULL )
return FALSE;
return TRUE;
}
As requested, here is a PoC program to recreate the issue I am facing. I am really hoping this will help you guys point me to a solution. Also, take note, the DLL is being unloading due to conditions in the application which I am targeting (hooks that are already set in that application), so Incrementing the Reference Count is required for my thread to run in the first place.
Also, I can't run more than one operation in the main thread as it has its own functionality to take care of and another thread is required on the side to take care of something else. They must also run simultaneously, hence I need to fix this issue of making more than one thread in an Incremented DLL.
// dllmain.cpp : Defines the entry point for the DLL application.
#pragma comment( linker , "/Entry:DllMain" )
#include <Windows.h>
#include <process.h>
UINT CALLBACK SecondThread( PVOID pParam )
{
MessageBox( NULL , __FUNCTION__ , "Which Thread?" , 0 );
return 0;
}
UINT CALLBACK FirstThread( PVOID pParam )
{
MessageBox( NULL , __FUNCTION__ , "Which Thread?" , 0 );
_beginthreadex(0, 0, &SecondThread, 0, 0, 0);
return 0;
}
BOOL IncrementReference( HMODULE hModule )
{
if ( hModule == NULL )
return FALSE;
TCHAR ModulePath[ MAX_PATH + 1 ];
if ( GetModuleFileName( hModule , ModulePath , MAX_PATH ) == 0 )
return FALSE;
if ( LoadLibrary( ModulePath ) == NULL )
return FALSE;
return TRUE;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
if (IncrementReference(0))
_beginthreadex(0, 0, &FirstThread, 0, 0, 0);
}
break;
}
return TRUE;
}
As you can see, the code never executes the SecondThread function. The question is, why? And what can be done to fix it?
#pragma comment( linker , "/Entry:DllMain" )
That was a very bad idea, the proper entrypoint for a DLL is not in fact DllMain(). You have to keep in mind that WinMain and DllMain are just place-holder names. A way for Microsoft to document the relevance of executable file entrypoints. By convention you use those same names in your program, everybody will understand what they do.
But there's a very important additional detail in a C or C++ program, the CRT (C runtime library) needs to be initialized first. Before you can run any code that might make CRT function calls. Like _beginthreadex().
In other words, the default /ENTRY linker option is not DllMain(). The real entrypoint of a DLL is _DllMainCRTStartup(). A function inside the CRT that takes care of the required initialization, then calls DllMain(). If you wrote one in your program then that's the one that runs. If you didn't then a dummy one in the CRT gets linked.
All bets are off when you make CRT function calls and the CRT wasn't initialized. You must remove that #pragma so the linker will use the correct entrypoint.
According to MSDN you schould neither call LoadLibrary nor CreateThread inside DllMain - your code does both!
The MCVE as posted has three problems:
The first is a simple mistake, you're calling IncrementReference(0) instead of IncrementReference(hModule).
The second is that there is no entry point for rundll32 to use; the entry point argument is mandatory, or rundll32 won't work (I don't think it even loads the DLL).
The third is the #pragma as pointed out by Hans.
After fixing the IncrementReference() call, removing the #pragma and adding an entry point:
extern "C" __declspec(dllexport) void __stdcall EntryPoint(HWND, HINSTANCE, LPSTR, INT)
{
MessageBoxA( NULL , __FUNCTION__ , "Which Thread?" , 0 );
}
You can then run the DLL like this:
rundll32 testdll.dll,_EntryPoint#16
This works on my machine; EntryPoint, FirstThread and SecondThread all generate message boxes. Make sure you do not dismiss the message box from EntryPoint prematurely, as that will cause the application to exit, taking the other threads with it.
The call to LoadLibrary is still improper, however it does not appear to have any side-effects in this scenario (probably because the library in question is guaranteed to already be loaded).
(Previous) Answer:
The MCVE can be fixed by simply moving the call to IncrementReference from DllMain to FirstThread. That is the only safe and correct way to resolve the problem.
Addendum: as Hans pointed out, you'll also need to remove the /Entry pragma.
(Redundant?) Commentary:
If the application that is loading the DLL is misbehaving to the extent where the DLL is being unloaded before FirstThread can run, and assuming for the sake of argument that you can't fix it, the only realistic option is to work around the problem - for example, DllMain could suspend all the other threads in the process so that they cannot unload the DLL, and resume them from FirstThread after the call to IncrementReference.
Or you could try hooking FreeLibrary, or reverse engineering the loader and messing with the reference count directly, or removing the hooks the application has placed, or loading a separate copy of the DLL by hand inside DllMain (with your own DLL loader rather than the one Windows provides) or starting a separate process and working from there or, oh, no doubt there's any number of other possibilities, but at that point I'm afraid the question really is too broad for Stack Overflow, particularly since you can't give us the real details of what the application is doing.

How to recover from COM error gracefully?

I have a third party COM component with its c++ interface in VC++. I am getting a crash in the call below which is crashing my application. How can I recover gracefully from this function which is not really part of my application?
inline _RecordsetPtr IGLibMgr::GetLibInfo ( _bstr_t LibPath ) {
struct _Recordset * _result = 0;
HRESULT _hr = raw_GetLibInfo(LibPath, &_result);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _RecordsetPtr(_result, false);
}
It crashes in the last line. I don't think I can modify this code since it's third party COM stuff. What options do I really have? I just want to bring up message box to user and return gracefully.
If you're not already doing this in your code, you need to be from the caller-side:
try
{ // setup your invoke for your object...
IGLibMgrPtr spMgr = ....
bstr_t bstrPath = ....
// invoke your call.
_RecordsetPtr spRS = spMgr->GetLibInfo(bstrPath);
... continue normal processing ...
}
catch(const _com_error& ce)
{
// handle your error here.
}
This is important on multiple levels. The most obvious being that not only can your IGLibMgr member throw an exception, so can the bstr_t allocation, etc. When using #import code from a COM DLL, get used to this format if using generated smart-pointers from the comutil library of MSVC.
Note: The _com_error class provides several members for obtaining why the error happened, including the HRESULT, error description string, etc. It even provides access to the IErrorInfo created by the error-returning object if it is so-nice as to provide that level of detail.

Under what conditions is CCmdTarget::OnFinalRelease called?

The MSDN documentation for the CCmdTarget::OnFinalRelease method is pretty brief:
Called by the framework when the last OLE reference to or from the
object is released.
I have created a sub-class of CCmdTarget
class CMyEventHandler : public CCmdTarget { ... }
I'm trying to figure out under what conditions the OnFinalRelease method will be called. I have some code that looks something like this:
CMyEventHandler* myEventHandler = new CMyEventHandler();
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionAdvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
// Application continues...events arrive...eventually the event sink is shutdown
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
Using this code, I observe that the OnFinalRelease method is never called. This means I have a memory leak. So I modified the wrap-up code as follows:
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
delete myEventHandler;
myEventHandler = NULL;
This section of code is triggered off periodically throughout the day. What I notice now is that, while the destructor for the wrapped up instance of myEventHandler is called as expected, the OnFinalRelease function is getting called now! What's worse, it is being called not on the instance that has been wrapped up, but instead on a newly created instance of CMyEventHandler! Thinking that this might be due to a reference counting issue, I modified my wire-up and wrap-up code:
CMyEventHandler* myEventHandler = new CMyEventHandler();
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(TRUE);
AfxConnectionAdvise(myEventSource, DIID_IMyEventInterface, pUnk, TRUE, myCookie);
pUnk->Release();
// Application continues...events arrive...eventually the event sink is shutdown
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(TRUE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, TRUE, myCookie);
pUnk->Release();
delete myEventHandler;
myEventHandler = NULL;
I let this run all day and now observe that OnFinalRelease is never called. The destructor for the wrapped up instance is called as I would expect, but I'm left feeling uneasy as I clearly don't understand the circumstances under which OnFinalRelease is called. Is OnFinalRelease called on some delay, or is there a way to force it to fire? What will trigger OnFinalRelease to be called?
If it matters, the event source is a .NET assembly exposing events via COM interop.
With COM you should always use the CoCreateInstance() AddRef() and Release() paradigm to manage lifetime of your objects, and let COM do the destruction of your objects based on reference counts. Avoid new and delete because using them breaks this paradigm and causes interesting side effects. You probably have a bug in the management of the reference counts.
The way to debug why the reference counts are not being managed correctly is to override CCmdTarget::InternalRelease() copy the source from oleunk.cpp and put some trace output or break points.
DWORD CMyEventHandler::InternalRelease()
{
ASSERT(GetInterfaceMap() != NULL);
if (m_dwRef == 0)
return 0;
LONG lResult = InterlockedDecrement(&m_dwRef);
if (lResult == 0)
{
AFX_MANAGE_STATE(m_pModuleState);
OnFinalRelease();
}
return lResult;
}
There are lots of times when passing IDispatch interfaces that code will bump reference counts and you have to decrement the reference count using Release(). Pay attention to where your code may be passing this interface because there is aconvention in COM that when Interfaces are passed using [in] or [out] where the caller or callee has to release the interface.
When the reference count issue is corrected you shoudl see the objects OnFinalRelease code being called and the object destoryed by hte MFC framework:
For CCmdTarget the destruction should happen as a result of the final
release in the parent class CWnd:
void CWnd::OnFinalRelease()
{
if (m_hWnd != NULL)
DestroyWindow(); // will call PostNcDestroy
else
PostNcDestroy();
}
FYI: Passing interfaces across threads without marshalling the interface pointers is another common reason to get errors in COM.
It doesn't appear that you ever call myEventHandler->Release(). Therefore, the last reference is never released, and OnFinalRelease is never called.

Uninitialized read problem

Program works fine (with random crashes) and Memory Validator reports Uninitialized read problem in pD3D = Direct3DCreate9.
What could be the problem ?
init3D.h
class CD3DWindow
{
public:
CD3DWindow();
~CD3DWindow();
LPDIRECT3D9 pD3D;
HRESULT PreInitD3D();
HWND hWnd;
bool killed;
VOID KillD3DWindow();
};
init3D.cpp
CD3DWindow::CD3DWindow()
{
pD3D=NULL;
}
CD3DWindow::~CD3DWindow()
{
if (!killed) KillD3DWindow();
}
HRESULT CD3DWindow::PreInitD3D()
{
pD3D = Direct3DCreate9( D3D_SDK_VERSION ); // Here it reports a problem
if( pD3D == NULL ) return E_FAIL;
// Other not related code
VOID CD3DWindow::KillD3DWindow()
{
if (killed) return;
diwrap::input.UnCreate();
if (hWnd) DestroyWindow(hWnd);
UnregisterClass( "D3D Window", wc.hInstance );
killed = true;
}
Inside main app .h
CD3DWindow *d3dWin;
Inside main app .cpp
d3dWin = new CD3DWindow;
d3dWin->PreInitD3D();
And here is the error report:
Error: UNINITIALIZED READ: reading register ebx
#0:00:02.969 in thread 4092
0x7c912a1f <ntdll.dll+0x12a1f> ntdll.dll!RtlUnicodeToMultiByteN
0x7e42d4c4 <USER32.dll+0x1d4c4> USER32.dll!WCSToMBEx
0x7e428b79 <USER32.dll+0x18b79> USER32.dll!EnumDisplayDevicesA
0x4fdfc8c7 <d3d9.dll+0x2c8c7> d3d9.dll!DebugSetLevel
0x4fdfa701 <d3d9.dll+0x2a701> d3d9.dll!D3DPERF_GetStatus
0x4fdfafad <d3d9.dll+0x2afad> d3d9.dll!Direct3DCreate9
0x00644c59 <Temp.exe+0x244c59> Temp.exe!CD3DWindow::PreInitD3D
c:\_work\Temp\initd3d.cpp:32
Edit: Your stack trace is very, very strange- inside the USER32.dll? That's part of Windows.
What I might suggest is that you're linking the multi-byte Direct3D against the Unicode D3D libraries, or something like that. You shouldn't be able to cause Windows functions to trigger an error.
Your Memory Validator application is reporting false positives to you. I would ignore this error and move on.
There is no copy constructor in your class CD3DWindow. This might not be the cause, but it is the very first thing that comes to mind.
If, by any chance, anywhere in your code a temporary copy is made of a CD3DWindow instance, the destructor of that copy will destroy the window handle. Afterwards, your original will try to use that same, now invalid, handle.
The same holds for the assignment operator.
This might even work, if the memory is not overwritten yet, for some time. Then suddenly, the memory is reused and your code crashes.
So start by adding this to your class:
private:
CD3DWindow(const CD3DWindow&); // left unimplemented intentionally
CD3DWindow& operator=(const CD3DWindow&); // left unimplemented intentionally
If the compiler complains, check the code it refers to.
Update: Of course, this problem might apply to all your other classes. Please read up on the "Rule of Three".

Thread Terminating Early with Code 255

I'm attempting to run a part of my program in a thread and getting an unusual result.
I have updated this question with the results of the changes suggested by Remus, but as I am still getting an error, I feel the question is still open.
I have implemented functionality in a dll to tie into a piece of vendor software. Everything works until I attempt to create a thread inside this dll.
Here is the relevant section of the DLL:
extern "C" {
__declspec(dllexport) void __cdecl ccEntryOnEvent(WORD event);
}
to define the function the vendor's software calls, then:
using namespace std;
HANDLE LEETT_Thread = NULL;
static bool run_LEETT = true;
unsigned threadID;
void *lpParam;
int RunLEETTThread ( void ) {
LEETT_Thread = (HANDLE)_beginthreadex( NULL, 0, LEETT_Main, lpParam, 0 , &threadID );
//LEETT_Thread = CreateThread ( NULL, 0, LEETT_Main, lpParam, 0 , NULL );
if ( LEETT_Thread == NULL )
ErrorExit ( _T("Unable to start translator thread") );
run_LEETT = false; // We only wish to create the thread a single time.
return 0;
}
extern "C" void __cdecl ccEntryOnEvent(WORD event ) {
switch (event) {
case E_START:
if ( run_LEETT ) {
RunLEETTThread ();
MessageText ( "Running LEETT Thread" );
}
break;
}
WaitForSingleObject( LEETT_Thread ,INFINITE);
return;
}
The function is declared as
unsigned __stdcall LEETT_Main ( void* lpParam ) {
LEETT_Main is about 136k when compiled as a stand alone executable with no optimization (I have a separate file with a main() in it that calls the same function as myFunc).
Prior to changing the way the thread is called, the program would crash when declaring a structure containing a std::list, shown here:
struct stateFlags {
bool inComment; // multiline comments bypass parsing, but not line numbering
// Line preconditions
bool MCodeSeen; // only 1 m code per block allowed
bool GCodeSeen; // only 1 g code per block allowed
std::list <int> gotos; // a list of the destination line numbers
};
It now crashes on the _beginthreadex command, tracing through shows this
/*
* Allocate and initialize a per-thread data structure for the to-
* be-created thread.
*/
if ( (ptd = (_ptiddata)_calloc_crt(1, sizeof(struct _tiddata))) == NULL )
goto error_return;
Tracing through this I saw a error 252 (bad ptr) and ultimately 255 (runtime error).
I'm wondering if anyone has encountered this sort of behaviour creating threads (in dlls?) and what the remedy might be. When I create an instance of this structure in my toy program, there was no issue. When I removed the list variable the program simply crashed elsewhere, on the declaration of a string
I'm very open to suggestions at this point, if I have to I'll remove the idea of threading for now, though it's not particularly practical.
Thanks, especially to those reading this over again :)
Threads that use CRT (and std::list implies CRT) need to be created with _beginthreadex, as documented on MSDN:
A thread in an executable that calls the C run-time library (CRT)
should use the _beginthreadex and _endthreadex functions for thread
management rather than CreateThread and ExitThread;
Is not clear how you start your thread, but it appears that you're doing it in DllMain which is not recommended (see Does creating a thread from DllMain deadlock or doesn't it?).
In rechecking the comments here and the configuration of the project, the vendor supplied solution file uses /MTd for debug, but we are building a DLL, so I needed to use /MDd, which immediately compiles and runs correctly.
Sorry about the ridiculous head scratcher...