Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving Error R6016 - Not enough space for thread data

My statically-linked Visual C++ 2012 program sporadically generates a CRTL error: "R6016 - Not enough space for thread data".

The minimal documentation from Microsoft says this error message is generated when a new thread is spawned, but not enough memory can be allocated for it.

However, my code only explicitly spawns a new thread in a couple of well-defined cases, neither of which are occurring here (although certainly the Microsoft libraries internally spawn threads at well). One user reported this problem when the program was just existing in the background.

Not sure if it's relevant, but I haven't overridden the default 1MB reserved stack size or heap size, and the total memory in use by my program is usually quite small (3MB-10MB on a system with 12GB actual RAM, over half of which is unallocated).

This happens very rarely (so I can't track it down), and it's been reported on more than one machine. I've only heard about this on Windows 8.1, but I wouldn't read too much into that.

Is there some compiler setting somewhere that might influence this error? Or programming mistake?

like image 656
Dev93 Avatar asked Jan 15 '14 01:01

Dev93


2 Answers

This turned out to be caused by calling CreateThread rather than _beginthread. Microsoft documentation in the Remarks section states that CreateThread causes conflicts when using the CRT library, and indeed, once we made the change, we never saw that error again.

like image 73
Dev93 Avatar answered Oct 03 '22 07:10

Dev93


You have to call TlsAlloc in DllMain if the Windows version is Vista or higher .

implicit TLS handling was rewritten in Windows Vista [...] threadprivate and __declspec(thread) should function correctly in run-time loaded DLLs since then.

BOOL APIENTRY DllMain(HINSTANCE hinstDll, DWORD fdwReason,
           LPVOID lpvReserved)
   {
       static BOOL fFirstProcess = TRUE;
       BOOL fWin32s = FALSE;
       DWORD dwVersion = GetVersion();
       static DWORD dwIndex;

       if ( !(dwVersion & 0x80000000) && LOBYTE(LOWORD(dwVersion))<4 )
           fWin32s = TRUE;

       if (dwReason == DLL_PROCESS_ATTACH) {
           if (fFirstProcess || !fWin32s) {
               dwIndex = TlsAlloc();
            }
            fFirstProcess = FALSE;
       }

   }

kb 118816

When a program is started the size of the TLS is determined by taking into account the TLS size required by the executable as well as the TLS requirements of all other implicitly loaded DLLs. When you load another DLL dynamically with LoadLibrary or unload it with FreeLibrary, the system has to examine all running threads and to enlarge or compact their TLS storage accordingly.

Your DLL code should be modified to use such TLS functions as TlsAlloc, and to allocate TLS if the DLL is loaded with LoadLibrary. Or, the DLL that is using __declspec(thread) should only be implicitly loaded into the application.

Bottom line: LoadLibrary ain't thread-safe.

like image 42
Stefan Steiger Avatar answered Oct 03 '22 07:10

Stefan Steiger