I have a Win32 DLL written in C which I call from a variety of environments
like VB, VB.NET and C#.
The DLL is written to be thread-safe and uses TLS written as recommended by
Microsoft in "Using Thread Local Storage in a Dynamic-Link Library"
<http://msdn.microsoft.com/library/de...-us/dllproc/ba
se/using_thread_local_storage_in_a_dynamic_link_libra ry.asp>
or <http://tinyurl.com/p3jgy>. My version of the code is reproduced below.
In a plain EXE program written in C, statically linked, it works perfectly,
even when multiple threads are called.
But if I call functions in the DLL from a .NET program (using [DllImport] in
C# or Public Declare Function in VB.NET), it seems to attach threads more
times than it detaches them and so there is a memory leak.
I suspect that this is also the cause of a memory leak in an adaptation to
call the DLL from PowerBuilder.
I always thought the problem with TLS was that DLL_THREAD_ATTACH might get
bypassed and you had to manage unallocated storage in your program. In this
case not all threads seem to call DLL_THREAD_DETACH.
Does this mean I have to write my own handler to free all allocated storage
when the process exits? If so, it would seem to defeat the use of TLS in the
first place.
Any suggestions?
=====(code)=====
static DWORD dwTlsIndex; // address of shared memory
BOOL DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
LPVOID lpvData;
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// Allocate a TLS index.
if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
return FALSE;
// No break: Initialize the index for first thread.
case DLL_THREAD_ATTACH:
lpvData = calloc(MY_BLOCK_LEN, 1);
if (lpvData != NULL)
fIgnore = TlsSetValue(dwTlsIndex, lpvData);
break;
case DLL_THREAD_DETACH:
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
free(lpvData);
break;
case DLL_PROCESS_DETACH:
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
free(lpvData);
TlsFree(dwTlsIndex);
// Check for memory leaks
_CrtDumpMemoryLeaks();
break;
default:
break;
}
return TRUE;
}
=====(end code)=====