I have a non sistematic crash (R6016) when our application is about to terminate. The application is composed of several DLL.
After a little investigation, we found the problem inside a function of mscvrt ( VS 2010) :
_ptiddata __cdecl _getptd_noexit (
void
)
{
_ptiddata ptd;
DWORD TL_LastError;
TL_LastError = GetLastError();
#ifdef _M_IX86
/*
* Initialize FlsGetValue function pointer in TLS by calling __set_flsgetvalue()
*/
if ( (ptd = (__set_flsgetvalue())(__flsindex)) == NULL ) {
#else /* _M_IX86 */
if ( (ptd = FLS_GETVALUE(__flsindex)) == NULL ) {
#endif /* _M_IX86 */
/*
* no per-thread data structure for this thread. try to create
* one.
*/
#ifdef _DEBUG
extern void * __cdecl _calloc_dbg_impl(size_t, size_t, int, const char *, int, int *);
if ((ptd = _calloc_dbg_impl(1, sizeof(struct _tiddata), _CRT_BLOCK, __FILE__, __LINE__, NULL)) != NULL) {
#else /* _DEBUG */
if ((ptd = _calloc_crt(1, sizeof(struct _tiddata))) != NULL) {
#endif /* _DEBUG */
if (FLS_SETVALUE(__flsindex, (LPVOID)ptd) ) {
/*
* Initialize of per-thread data
*/
_initptd(ptd,NULL);
ptd->_tid = GetCurrentThreadId();
ptd->_thandle = (uintptr_t)(-1);
}
else {
/*
* Return NULL to indicate failure
*/
_free_crt(ptd);
ptd = NULL;
}
}
}
SetLastError(TL_LastError);
return(ptd);
}
This function is called normally during process shutdown and normally it works. When it doesn't work it returns NULL; analyzing the code the point of failure are:
calloc_crt
returns NULL, ie it can't alloc memoryFLS_SETVALUE
returns 0
FLS_SETVALUE is a macro that calls FlsSetValue
. It receives a global var, __flsindex, that is the index for fiber
allocated with FlsAlloc
.
__flsindex is resetted at termination of process in the ctr function of _mtterm
I think that crt is shutting down prematurely, before another DLL that use it but i don't know why.
Our program doesn't call CreateThread
.
So my question is:
- how dll are terminated and in which order? is it deterministic or changes from execution to execution?
- how can I investigate further?