Разрешение ошибки R6016 - недостаточно места для данных потока
моя статически связанная программа Visual C++ 2012 спорадически генерирует ошибку CRTL:"R6016 - недостаточно места для данных потока".
минимальная документация от Microsoft говорит, что это сообщение об ошибке генерируется при создании нового потока, но для него может быть выделено недостаточно памяти.
однако мой код только явно порождает новый поток в нескольких четко определенных случаях, ни один из которых не происходит здесь (хотя, конечно, библиотеки Microsoft внутренне нерестятся нити в скважине). Один пользователь сообщил об этой проблеме, когда программа просто существовала в фоновом режиме.
Не уверен, что это актуально, но я не переопределил размер зарезервированного стека по умолчанию 1MB или размер кучи, а общая память, используемая моей программой, обычно довольно мала (3MB-10MB в системе с 12GB фактической ОЗУ, более половины из которых нераспределена).
Это происходит очень редко (поэтому я не могу отследить его), и сообщалось о более чем одном машина. Я только слышал об этом в Windows 8.1, но я бы не стал слишком много читать об этом.
есть ли какая-то настройка компилятора, которая может повлиять на эту ошибку? Или ошибка программирования?
3 ответов
Это оказалось вызвано вызовом CreateThread, а не _beginthread. В документации Microsoft в разделе Примечания указано, что CreateThread вызывает конфликты при использовании библиотеки CRT, и действительно, как только мы внесли изменения, мы больше никогда не видели этой ошибки.
вы должны вызвать 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;
}
}
при запуске программы размер TLS определяется путем принятия учетом размера ТЛС требует исполняемый как также Требования TLS всех других неявно загруженных библиотек DLL. При загрузке другая DLL динамически с LoadLibrary или выгрузить его с FreeLibrary, система должна изучить все запущенные потоки и увеличьте или компактируйте их хранилище TLS соответственно.
ваш DLL-код должен быть изменен, чтобы использовать такие функции TLS, как TlsAlloc, и выделять TLS, если DLL загружена LoadLibrary. Или DLL, использующая _ _ declspec (thread) , должна быть загружена только неявно в приложение.
итог: LoadLibrary не является потокобезопасным.
Я обнаружил, что процесс находится в 32 бит. В этом случае я увеличиваю память для обработки с помощью команды
bcdedit / set increaseuserva 3072