Столкнулся с проблемой в большом проекте, в итоге смог ее выцедить и привожу остаток. 1. Есть нативная DLL, написанная на C++, которая использует динамический TLS (может быть собрана как со статическими рантаймами, так и с динамическими, на появление проблемы это никак не влияет). 2. Есть обертка для этой DLL, написанная на C++/CLI, которая пробрасывает функции библиотеки в .NET. 3. Есть программа на C#, которая использует функции через обертку. Если из C# вызвать любую функцию библиотеки, использующую TLS (TlsGetValue), сначала из одного потока, а потом из другого, то программа падает на втором вызове: И это только в том случае, если программа под отладкой VS (используется версия 2010). Кроме того, если включить галку "Enable unmanaged code debugging" (см. картиночку ниже), то и под отладкой падения прекращаются! Вопрос к знатокам: возможно, кто-то с таким сталкивался. В чем ошибка - в отладчике? Косяки с TLS? Что-то еще? Почему включение флажка для дебага неуправляемого кода исправляет падения? Дабы не быть голословным, прилагаю солюшен 2010-й студии, в котором три вышеперечисленных проекта. DLL-ка с TLS взята буквально с MSDN, из мануала по работе с TLS. Соберите в Debug/Release режиме и запустите под отладкой. С первого (иногда со второго) запуска начинает валиться. Все собирается в Visual Studio 2010, используется .NET 3.5 (можно и 2.0, с 4.0 не пробовал). Сходу может не собраться, тогда придется поменять рантаймы c++ (сейчас в настройках прописано использование 9.0 рантаймов). Заранее благодарен за помощь, ломаю голову уже третий день. Ах да, совсем забыл сказать - если к C++/CLI врапперу нативную DLL линковать не статически, а динамически через LoadLibrary, нифига не меняется. UPDATE: с 4м дотнетом тоже падает под отладкой.
Проблема наконец-то решена, всем спасибо, можно закрывать. Проблема в том, что .NET может подгрузить DLL в любой момент, когда несколько потоков уже созданы, а DLL о них ничего, соответственно, не узнает, и DLL_THREAD_ATTACH для них не выполнится. Решение - при использовании функции, дергающей TLS, отдельно каждый раз проверять возвращенное TlsGetValue значение, и если оно равно нулю, то инициализировать TLS в потоке вызовом TlsSetValue. В DLL_THREAD_DETACH также обязательно сделать проверку полученного из TlsGetValue значения на ноль.