16

我的静态链接 Visual C++ 2012 程序偶尔会生成一个 CRTL 错误:“R6016 - 没有足够的空间用于线程数据”。

Microsoft 的最小文档说,当产生新线程时会生成此错误消息,但无法为其分配足够的内存。

但是,我的代码仅在几个定义明确的情况下显式生成了一个新线程,这两种情况都没有发生(尽管 Microsoft 库内部肯定会生成线程)。当程序刚刚存在于后台时,一位用户报告了此问题。

不确定它是否相关,但我没有覆盖默认的 1MB 保留堆栈大小或堆大小,并且我的程序使用的总内存通常很小(在具有 12GB 实际 RAM 的系统上为 3MB-10MB,超过一半这是未分配的)。

这种情况很少发生(所以我无法追踪它),并且报告在不止一台机器上。我只在 Windows 8.1 上听说过这个,但我不会对此进行过多解读。

是否有一些编译器设置可能会影响此错误?还是编程错误?

4

3 回答 3

4

结果证明这是由调用 CreateThread 而不是 _beginthread 引起的。备注部分中的 Microsoft 文档指出CreateThread 在使用 CRT 库时会导致冲突,实际上,一旦我们进行了更改,我们就再也没有看到该错误。

于 2014-09-24T20:32:22.233 回答
1

如果 Windows 版本是 Vista 或更高,您必须在 DllMain 中调用 TlsAlloc。

在 Windows Vista [...] threadprivate 中重写了隐式 TLS 处理,并且 __declspec(thread) 从那时起应该在运行时加载的 DLL 中正常工作。

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;
       }

   }

知识库 118816

当程序启动时,TLS 的大小是通过考虑可执行文件所需的 TLS 大小以及所有其他隐式加载的 DLL 的 TLS 要求来确定的。当您使用 LoadLibrary 动态加载另一个 DLL 或使用 FreeLibrary 卸载它时,系统必须检查所有正在运行的线程并相应地扩大或压缩它们的 TLS 存储。

应修改您的 DLL 代码以使用诸如 TlsAlloc 之类的 TLS 函数,并在 DLL 使用 LoadLibrary 加载时分配 TLS。或者,使用 __declspec(thread) 的 DLL 应该只隐式加载到应用程序中。

底线:LoadLibrary 不是线程安全的。

于 2014-08-04T13:58:17.750 回答
0

我发现该进程是 32 位的。在这种情况下,我会增加内存以使用命令进行处理

bcdedit /set increaseuserva 3072

于 2017-09-29T12:30:06.390 回答