From: Bronek Kozicki (brok_at_[hidden])
Date: 2004-07-30 03:42:14
>>TlsSetValue and initialization of CRT data is delayed to first access of
>>CRT TLS data through _getptd function (defined in tidtable.c).
> Ahhh. Now I understand what you are talking about!
> You convinced me.
> During DLL_THREAD_DETACH the _tiddata has already been deallocated during
> _endthread. Now if one again accesses one of the CRT functions during DLL_THREAD_DEATCH
> this would cause _getptd to reallocate _tiddata for this thread.
> Hmm. This will also account for a memory leak. Wouldn't it?
Probably yes. But :
* if CRT is statically linked to dynamic library, user's DllMain is
called prior to releasing CRT data
* if CRT is dynamically linked to program or some of it's libraries, I
think that it will receive DLL_THREAD_DETACH notification after user
dynamic libraries handled it (reverse order of loading libraries). I'm
not sure about that.
You would still have memory leak if using staticaly linked CRT *and*
nobody is handling DLL_THREAD_DETACH for this TLS CRT index. But that
does not apply to Windows Server 2003, see below.
In case of Windows Server 2003 there is callback function called
FlsCallback, documented here:
It's called inside ThreadExit, in context of exiting thread, *after* all
DLLs received notification DLL_THREAD_DETACH. Actually, CRT in MSVC71 is
using Fls* functions if available; function _freefls (defined by CRT)
will be called to *reliably* release CRT TLS (or actually fiber local
storage) on Windows Server 2003. You may find that in file tidtable.c
(available with MSVC71, directory vc7/crt/src). I'm seeking for a way to
achieve similar functionality in little older versions of Windows - but
it might be quite difficult.
> While the situation is not as bad as I was afraid it could be,
> it still would be better to be able to call the tls cleanup code from
> within _endthread, and not DLL_THREAD_DETACH.
Hm, _endthread is executed before notifications DLL_THREAD_DETACH are
sent in ExitThread. Or more precisely - ExitThread is called at the end
of _endthread, and there is no way one could execute code after this
call. Thus if user DllMain is expecting to find data that has been
released in _endthread, that might be a problem (eg. in case of CRT -
another allocation inside _getptd).