Is it possible to do this?
TIA,
john
suppose you can unload a dll with outstanding reference there, the memory
occupied by the dll is released, and then someone (atl in your case) calls
into some function exported by this dll. i bet that you will see access
violation error immediately.
thanks
wei
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Got .Net? http://www.gotdotnet.com
You can probably force the DLL to unload, but it will almost definitely
cause the module to generate an exception. Any access to the DLL by the
module after you unload it will be fatal to your program.
--
-Gary Chanson (MVP for Windows SDK)
-Software Consultant (Embedded systems and Real Time Controls)
-gcha...@mvps.org
-War is the last resort of the incompetent.
Eugene
"Johna" <jarr...@alarismed.com> wrote in message
news:Olcfn3UdCHA.2248@tkmsftngp11...
I am using IMallocSpy to report on memory leaks. MSXML4 has allocated some
sort of memory but is not releasing it until DLL unload time. The dll is not
unloading at CoUninitialize for some reason. It seems to be unloading at the
TerminateProcess() call in the crt exit routines. At that time it releases
the memory, calling IMallocSpy -- which is long gone -- so an exception is
thrown.
I have used this IMallocSpy code on many many COM objects MS and non-MS and
yes it works fine. The problem is msxml3/4.dll
"Eugene Gershnik" <gers...@hotmail.com> wrote in message
news:e4ZpbxbdCHA.2136@tkmsftngp09...
> If you are certain that you do not have an outstanding references to COM
> objects implemented in this dll then CoFreeUnusedLibraries(Ex)
> will probably help you. If it doesn't unload the dll it means you are
still using it somewhere.
I have tried a GetModuleHandle() and a FreeLibrary. Unfortunately, the
GetModuleHandle is returning 0. The GetLastError returns a 126 which is
"ERROR_MOD_NOT_FOUND". Yes, I've tried it with the full path and just a
file name too. So no joy.
I just tried CoFreeUnusedLibraries(). Sorry no joy. (CoFreeUnusedLibraries
is XP only).
> Try to call FreeLibrary on it and see where your code crashes to get an
idea where you
> hold it :-):-):-)
I don't hold a thing on this. All I'm doing is creating an instance of an
interface held within msxml and then immediately releasing it. I have used a
smart pointer and used the raw interface pointers as well. No joy either
way.
http://msdn.microsoft.com/library/en-us/wcedcom/htm/cerefCoRevokeMallocSpy.a
sp
-jw
--
Jon Wiswall - Microsoft
This posting is provided AS IS with no warranties, and confers no rights.
"Johna" <jarr...@alarismed.com> wrote in message
news:Oa1oMLfdCHA.1692@tkmsftngp09...
I do call it. The sequence of things occuring is:
---- Start of main()
- IMallocSpy implementation is created and registered
- CoInitialize is called
- msxml4 gets loaded
- an instance of IXMLDOMDocument gets created
- the instance is released
- CoUninitialize is called
- the memory leak report is done
- IMallocSpy is revoked
- IMallocSpy implementation is deleted
---- end of main()
- CRT is terminated
- TerminateProcess() is called
- msxml4 is unloaded
- a location inside of oleaut32 throws an exception
If I comment out the IMallocSpy implementation no exception is thrown.
Therefore msxml4 is still calling IMallocSpy whether I call revoke or not.
Also check out the CoRevokeMallocSpy documentation. It says that if memory
is still allocated, CoRevokeMallocSpy does not do a revoke it just marks
that there is a revoke pending. So the IMallocSpy implementation is called
whether or not you do a revoke. Nice.
What I need to get the memory leak report to work correctly is for msxml4 to
be unloaded prior to the generating the report. Note that msxml4 doesn't
leak - it's just a question of when does it actually free the memory. My
best guess so far is at dll unload time.
would you like to write a simple sample to show the problem? i am
interested in this issue and would like to take a close look myself.
thanks
wei
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Got .Net? http://www.gotdotnet.com
Wei,
The code is below. Comment out the "delete ch;" line to prevent the
exception from happening.
The original code keeps track of all allocs and frees and then prints a
report. That report dumps out 10 unfreed allocations totalling 2694 bytes.
(I cross-posted this same question to microsoft.public.xml)
John
-------------------------------------------------
#include <atlbase.h> //for ComBSTR
//----------------------------------------------------------------------
//-- the extension of the IMallocSpy callback
class ComHeapSpy2 : public IMallocSpy
{
public:
ComHeapSpy2() {count = 0;}
~ComHeapSpy2() {}
private:
ULONG count;
ComHeapSpy2(const ComHeapSpy2&); //no copy
ComHeapSpy2& operator=(const ComHeapSpy2&); //no assignment
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void**ppv)
{
if (riid == IID_IUnknown || riid == IID_IMallocSpy)
LPUNKNOWN(*ppv = (IMallocSpy*)this)->AddRef();
else
*ppv = 0;
return ResultFromScode(*ppv ? S_OK : E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) AddRef() { return ++count; }
STDMETHODIMP_(ULONG) Release(){ return --count;}
// IMallocSpy methods
STDMETHODIMP_(ULONG) PreAlloc(ULONG cbRequest){ return cbRequest; }
STDMETHODIMP_(void*) PostAlloc(void *pActual) { return pActual; }
STDMETHODIMP_(void*) PreFree(void *pRequest, BOOL fSpyed) { return
pRequest; }
STDMETHODIMP_(void) PostFree(BOOL fSpyed) { }
STDMETHODIMP_(ULONG) PreRealloc(void *pRequest, ULONG cbRequest, void
**ppNewRequest, BOOL fSpyed){ return cbRequest; }
STDMETHODIMP_(void*) PostRealloc(void *pActual, BOOL fSpyed){return
pActual;}
STDMETHODIMP_(void*) PreGetSize(void *pRequest, BOOL fSpyed){return
pRequest;}
STDMETHODIMP_(ULONG) PostGetSize(ULONG cbActual, BOOL fSpyed){return
cbActual;}
STDMETHODIMP_(void*) PreDidAlloc(void *pRequest, BOOL fSpyed){return
pRequest;}
STDMETHODIMP_(int) PostDidAlloc(void *pRequest, BOOL fSpyed, int
fActual){return fActual;}
STDMETHODIMP_(void) PreHeapMinimize(void){}
STDMETHODIMP_(void) PostHeapMinimize(void){}
};
#import "msxml4.dll"
using namespace MSXML2;
void main()
{
ComHeapSpy2* ch = new ComHeapSpy2;
::CoRegisterMallocSpy(ch);
CoInitialize(0);
{
IXMLDOMDocumentPtr x;
x.CreateInstance(__uuidof(DOMDocument));
}
CoUninitialize();
//real code has calls a reporting function to dump leaks here...
::CoRevokeMallocSpy();
//delete ch; //comment this line to prevent the exception
}
One is how to use IMallocSpy correctly. Many samples (including a msj
article: www.microsoft.com/msj/1095/activex1095.htm) use a local variable
to store the spy object. My opinion is that this is not correct. We
should keep it live forever. A global variable is OK; dynamic-allocating
and never deleting it also works. Or else we will meet a problem as below,
When memory leak does happens, the CoRevokeMallocSpy returns E_ACCESSDENIED
and does not really revoke (i.e. unhook) the spy. That is, the spy object
is still uses for every IMalloc operation. If the execution is out of
local scope (i.e. returning from main but before completing ExitProcess),
the spy object has already been automatically destroyed. Later reference to
this pointer causes access violation immediately.
As to the second problem, I am not sure whether there is really a leak in
msxml4 and will leave this issue to people at microsoft.public.xml group.
However my test show that, if i try to create a object using some random
unregistered class guid (code as below), there is still 'leak' reported
from spy object. maybe it is a fake reporting (Q139071: INFO: OLE
Automation BSTR Caching & Finding Memory Leak Sources)?
void main()
{
CoInitialize(0);
ComHeapSpy2 *pSpy = new ComHeapSpy2;
CoRegisterMallocSpy(pSpy);
CoCreateInstance(random_unreg_clsid);
CoUninitialize();
CoRevokeMallocSpy();
}
hope this helps.
You are absolutely right. That's why I allocated spy on the heap. I put the
"delete ch" in there to show that msxml is calling IMallocSpy after
everything is shut down. If you follow the code execution all the way into
the CRT shutdown code, you'll see that the exception occurs during the
TerminateProcess() call when ole32 is doing something or other. My guess is
that msxml is finally freeing its memory at that point.
If I don't delete spy, it's a memory leak but that's ok. I can change my spy
code so that the spy object is allocated on a different NT heap and so it
won't show up on the CRT memory leak reports (i.e. _Crtxxx routines)
> As to the second problem, I am not sure whether there is really a leak in
> msxml4 and will leave this issue to people at microsoft.public.xml group.
> However my test show that, if i try to create a object using some random
> unregistered class guid (code as below), there is still 'leak' reported
> from spy object. maybe it is a fake reporting (Q139071: INFO: OLE
> Automation BSTR Caching & Finding Memory Leak Sources)?
BSTRs are cached and when I use SysAllocString, I see some memory
allocations which I assume are the cache container and other associated
objects for the cache. My experiments have shown that the cache is cleaned
up during the CoUninitialize() if all the BSTRs are cleaned up as well.
I've also seen a bit of one-time memory allocated when the first COM object
is allocated. But again it's cleaned up when CoUninitialize is called.
There's other situations where memory is allocated but not freed for a
while. One trick I've used is to add a Sleep(10000) after the CoUninitialize
and before my spy report to give the COM components a chance to free there
memory.
I don't think the msxml4 memory is any of these situations. I'm speculating
but I think msxml is allocating memory at DLL load and de-allocating it at
DLL unload. But for some reason the DLL is not unloading when the last
instance of the msxml is freed and the CoUninitialize is done.
BTW I just installed mxsml4 SP2 and it still fails in the same way.
> I think msxml is allocating memory at DLL load and de-allocating it at
DLL unload
I have tested msxml3/4 and some other components (e.g. CLSID_ShellLink) on
winxp machine with following code:
hr = CoCreateInstance(CLSID, &p);
if(SUCCEEDED(hr)) p->Release;
the result is the same: the IMallocSpy::PreFree is called when the process
exits. the call stack also shows that the caller is ole32!dllmain and
clbcatq!dllmain. looks like com is doing some internal work here. maybe
it is not a problem in msxml.