Разрешение ошибки R6016 - Недостаточно места для данных потока

Моя статически связанная программа Visual С++ 2012 спорадически генерирует ошибку CRTL: "R6016 - недостаточно места для данных потока".

Минимальная документация от Microsoft говорит, что это сообщение об ошибке генерируется, когда генерируется новый поток, но для него не может быть выделено достаточно памяти.

Однако мой код только явно порождает новый поток в нескольких четко определенных случаях, ни один из которых не встречается здесь (хотя, конечно, библиотеки Microsoft внутренне порождают потоки). Один пользователь сообщил об этой проблеме, когда программа только что была в фоновом режиме.

Не уверен, что это актуально, но я не переопределил размер зарезервированного стека по умолчанию в 1 МБ или размер кучи, а общая память, используемая моей программой, обычно довольно мала (3 МБ-10 МБ в системе с оперативной памятью 12 ГБ, более половины из которых нераспределены).

Это случается очень редко (так что я не могу его отследить), и это сообщалось на нескольких машинах. Об этом я только слышал в Windows 8.1, но я не стал бы слишком читать об этом.

Есть ли какая-нибудь настройка компилятора, которая может повлиять на эту ошибку? Или ошибка программирования?

Ответ 2

Вы должны вызвать TlsAlloc в DllMain, если версия Windows - Vista или выше.

неявная обработка TLS была переписана в Windows Vista [...] threadprivate и __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;
       }

   }

kb 118816

Когда программа запускается, размер TLS определяется путем принятия с учетом размера TLS, требуемого исполняемым файлом, а также TLS всех других неявно загружаемых библиотек DLL. Когда вы загружаете другой DLL динамически с LoadLibrary или выгрузить его с помощью FreeLibrary, система должна проверять все текущие потоки и соответственно увеличивайте или уплотняют их хранилище TLS.

Ваш DLL-код должен быть изменен для использования таких функций TLS, как TlsAlloc, и для выделения TLS, если DLL загружается с помощью LoadLibrary. Или DLL, использующая __declspec (thread), должна быть неявно загружена в приложение.

Нижняя строка: LoadLibrary не является потокобезопасной.

Ответ 3

Я обнаружил, что процесс находится в 32 бит. В этом случае я увеличиваю память для обработки с помощью команды

bcdedit/set enlargeuserva 3072