В пуле потоков Windows 10 есть ошибки - PullRequest
0 голосов
/ 18 марта 2020

Почему Windows 10 запускает дополнительные темы в моей программе?

Позволяет увидеть простой код,

class AA
{
...
};

AA& getAA(){
  static AA aa;
  return aa;
}

class BB
{
  public:  BB() { getAA(); ... }
...
};
thread_local BB bb;

Я добавил дополнительную информацию с чем я столкнулся.

. С помощью этого простого кода я переписываю стеки вызовов.

Исключение иногда выдается в 0x00007FFB0B1272A6 (ntdll.dll). Положение о нарушении прав доступа 0x000000024. Члены g_tss_mutex равны нулю, кроме LockCount, который был равен 6, и LockSemaphore, который был равен 0xffffffffffffffff. Функция _Init_thread_lock () и она вызывает EnterCriticalSection (& g_tss_mutex); Рабочий поток ntdll.dll поток выбрасывает это исключение. стек вызовов был.

ntdll.dll!00007ffb0b1272a6()
ntdll.dll!00007ffb0b13b5f6()
ntdll.dll!00007ffb0b13b440()
_init_thread_lock() 
_Init_thread_header(int *pOnce)
getAA()
BB::BB()
`dynamic initializer for 'bb'()

стек вызовов основного потока был

_should_initialize_environment()
pre_c_initialization()
ucrtbased.dll!00007ffe9c1a4ab9
__scrt_common_main_seh()
__scrt_common_main()
WinMainCrtStartup()
....

Потоки загрузчиков из пула потоков Windows 10 пытаются инициализировать thread_local bb. Но если потоки Loader вызывают конструктор bb до того, как основной поток процесса не вызовет _scrt_initialize_thread_safe_statics_platform_specifi c (), чтобы получить stati c magi c. https://docs.microsoft.com/en-us/cpp/build/reference/zc-threadsafeinit-thread-safe-local-static-initialization?view=vs-2019

Я встретил эту ситуацию. Что я могу сделать, чтобы решить эту проблему.

1 Ответ

0 голосов
/ 25 марта 2020

Даже если Windows Thread Pool не создаст свои собственные потоки, в вашем процессе всегда могут быть гости. Антивирусное программное обеспечение, программное обеспечение для управления, расширения оболочки, программное обеспечение для обеспечения доступности ... или даже вредоносное ПО.

Ключевая проблема здесь заключается в том, что thread_local создается уже при запуске потоков.

Вы можете помочь, сделав их конструктор constexpr только с инициализацией stati c, а затем выполнить любой динамический c материал.

Или обернуть свои thread_local объекты std::optional, и построить их, когда они нужны вам самим. Или создайте свою собственную обертку для этого.

Я понимаю, что все это обходные пути, и решением было бы то, что MSV C задержит создание локальной переменной потока. Но я доволен обходными путями. Если нет, отправьте отзыв MS.

В конечном счете, задерживая создание объекта thread_local, вы также оптимизируете: вы не создаете объект для потоков, в которых ваш код никогда не будет работать.

...