Re: shared DLL VS static Link, Are they different?
On Sun, 03 Aug 2008 16:15:17 +0800, asm23 <asmwarrior@gmail.com> wrote:
hi, everyone, I meet a strange problem:
I'm using VC6 and create a dialog based applications. And I want to add
a third part library( Open computer library--OpenCV AS DLL). I linked
with the cxcored.lib. My APP will call functions in cxcore001d.dll.
I only add two functions in the OnInitDialog function:
/////////////////////////////////////////////////////////////////
BOOL COpenCVdialogDlg::OnInitDialog()
{
......
m_iplImage = cvCreateImage(ImgSize,IPL_DEPTH_8U,IMAGE_CHANNELS);
cvReleaseImage(&m_iplImage);
......
}
////////////////////////////////////////////////////////////////
In the code above, I only create an Image and release it quickly, which
seems I do Nothing. ^_^ ,The two functions are exported from
cxcore100d.dll( associated with cxcored.lib)
Here comes my problem. When I build the APP with static MFC library, the
program works fine. But When I build the APP with "Using MFC as shared
DLL" option, there are many memory leak report when I exit the APP.
It is very strange that "using MFC as shared DLL" and "using MFC as a
static library" are much different? Otherwise, There are something wrong
with the source code generating cxcore100d.dll?
The order of initialization of library static duration data (e.g. globals)
is not as well defined for static linking vs. dynamic linking.
By the way, OpenCV is an open source library,so, I have the full source
code of "cxcore100d.dll" , I examine the code and can't find anything wrong.
Here is its DLL Main entry:
////////////////////////////////////////////////////////////////
#if defined WIN32 || defined WIN64
BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID )
{
CvContext *pContext;
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_TlsIndex = TlsAlloc();
if( g_TlsIndex == TLS_OUT_OF_INDEXES ) return FALSE;
//break;
case DLL_THREAD_ATTACH:
pContext = icvCreateContext();
if( pContext == NULL)
return FALSE;
TlsSetValue( g_TlsIndex, (LPVOID)pContext );
break;
case DLL_THREAD_DETACH:
if( g_TlsIndex != TLS_OUT_OF_INDEXES )
{
pContext = (CvContext*)TlsGetValue( g_TlsIndex );
if( pContext != NULL )
icvDestroyContext( pContext );
}
break;
case DLL_PROCESS_DETACH:
if( g_TlsIndex != TLS_OUT_OF_INDEXES )
{
pContext = (CvContext*)TlsGetValue( g_TlsIndex );
if( pContext != NULL )
icvDestroyContext( pContext );
}
TlsFree( g_TlsIndex );
break;
default:
;
}
return TRUE;
}
////////////////////////////////////////////////////////////////
I was confused that why the "break" statement is commented after the
"case DLL_PROCESS_ATTACH:"?
Perhaps because the author wanted the DLL_PROCESS_ATTACH case to fall
through to the DLL_THREAD_ATTACH case. If this is true, it would be much
clearer to replace:
//break;
with:
// FALLTHROUGH
Further more, the cvCreateImage and cvReleaseImage function in my APP is
regularly simple, they only allocate a piece of memory and delete it.
Thanks for reading my Post!
I would bet the problem is due to the non-MFC DLL loading before the MFC
DLL. This means the non-MFC DLL's static duration data is destroyed after
MFC exits, and if there is any memory that is freed at that time, MFC will
report it as leaked, since it is still allocated when MFC dumps leaks in
its DLL_PROCESS_DETACH. This is a long-standing defect in MFC, which has no
business dumping leaks; it should wait until the CRT DLL dumps leaks after
all static duration objects have been destroyed. For a workaround, see if
these messages help:
http://groups.google.com/group/microsoft.public.vc.debugger/msg/6b90e68f21529e56
http://groups.google.com/group/microsoft.public.vc.mfc/browse_frm/thread/73493ddec165a5cb/e651b944da9c619d?#e651b944da9c619d
Though I never tried it, the second one should help with those DLLs you
can't modify.
--
Doug Harrison
Visual C++ MVP