Смешиваем C++, C++/CLI, C#, TLS, получаем IDUNNO WTF

Тема в разделе "WASM.BEGINNERS", создана пользователем GRRRLPower, 23 ноя 2011.

  1. GRRRLPower

    GRRRLPower New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2010
    Сообщения:
    46
    Столкнулся с проблемой в большом проекте, в итоге смог ее выцедить и привожу остаток.

    1. Есть нативная DLL, написанная на C++, которая использует динамический TLS (может быть собрана как со статическими рантаймами, так и с динамическими, на появление проблемы это никак не влияет).
    2. Есть обертка для этой DLL, написанная на C++/CLI, которая пробрасывает функции библиотеки в .NET.
    3. Есть программа на C#, которая использует функции через обертку.

    Если из C# вызвать любую функцию библиотеки, использующую TLS (TlsGetValue), сначала из одного потока, а потом из другого, то программа падает на втором вызове:

    [​IMG]

    И это только в том случае, если программа под отладкой VS (используется версия 2010). Кроме того, если включить галку "Enable unmanaged code debugging" (см. картиночку ниже), то и под отладкой падения прекращаются!

    [​IMG]

    Вопрос к знатокам: возможно, кто-то с таким сталкивался. В чем ошибка - в отладчике? Косяки с 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м дотнетом тоже падает под отладкой.
     
  2. GRRRLPower

    GRRRLPower New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2010
    Сообщения:
    46
    Проблема наконец-то решена, всем спасибо, можно закрывать.
    Проблема в том, что .NET может подгрузить DLL в любой момент, когда несколько потоков уже созданы, а DLL о них ничего, соответственно, не узнает, и DLL_THREAD_ATTACH для них не выполнится. Решение - при использовании функции, дергающей TLS, отдельно каждый раз проверять возвращенное TlsGetValue значение, и если оно равно нулю, то инициализировать TLS в потоке вызовом TlsSetValue. В DLL_THREAD_DETACH также обязательно сделать проверку полученного из TlsGetValue значения на ноль.