Можно ли безопасно создавать потоки во время статической инициализации? - PullRequest
8 голосов
/ 18 сентября 2009

В какой-то момент я помню, что читал, что потоки нельзя безопасно создавать до первой строки main (), потому что компиляторы вставляют специальный код, чтобы заставить работу потоков работать во время статической инициализации. Так что, если у вас есть глобальный объект, который создает поток при создании, ваша программа может завершиться сбоем. Но сейчас я не могу найти оригинальную статью, и мне любопытно, насколько это сильное ограничение - действительно ли оно строго по стандарту? Это правда на большинстве компиляторов? Останется ли это в C ++ 0x? Возможно ли, чтобы компилятор, соответствующий стандартам, сам выполнял статическую инициализацию многопоточность? (например, обнаружение, что два глобальных объекта не касаются друг друга, и инициализация их в отдельных потоках для ускорения запуска программы)

Редактировать: Чтобы уточнить, я пытаюсь хотя бы понять, действительно ли реализации существенно отличаются в этом отношении, или это псевдостандарт. Например, технически стандарт позволяет перетасовывать компоновку элементов, принадлежащих различным спецификаторам доступа (public / protected / и т. Д.). Но никакой компилятор, о котором я знаю, на самом деле не делает этого.

Ответы [ 3 ]

6 голосов
/ 18 сентября 2009

То, о чем вы говорите, не строго на языке, а в библиотеке времени выполнения C (CRT).
Для начала, если вы создадите поток, используя собственный вызов, такой как CreateThread() в Windows, вы можете сделать это где угодно, потому что он идет прямо в ОС без вмешательства CRT.
Другой вариант, который у вас обычно есть, это использовать _beginthread(), который является частью CRT. Есть некоторые преимущества использования _beginthread(), такие как наличие многопоточного errno. Подробнее об этом можно прочитать здесь . Если вы собираетесь создавать потоки, используя _beginthread(), могут возникнуть некоторые проблемы, потому что инициализация, необходимая для _beginthread(), может отсутствовать.

Это касается более общего вопроса о том, что именно происходит до main() и в каком порядке. По сути, у вас есть функция точки входа в программу, которая позаботится обо всем, что должно произойти до main() с Visual Studio, вы на самом деле можете посмотреть на этот кусок кода, который находится в CRT, и выяснить для себя, что именно там происходит. Самый простой способ добраться до этого кода - остановить точку останова в вашем коде и просмотреть кадры стека до main()

2 голосов
/ 21 сентября 2009

Основной проблемой является ограничение Windows на то, что вы можете и не можете делать в DllMain. В частности, вы не должны создавать потоки в DllMain. Статическая инициализация часто происходит из DllMain. Затем логически следует, что вы не можете создавать потоки во время статической инициализации.

0 голосов
/ 23 сентября 2009

Насколько я могу судить по чтению черновика C ++ 0x / 1x, запуск потока до main() - это нормально, но все же подвержен обычным ошибкам статической инициализации. Соответствующая реализация должна убедиться, что код для инициализации потоков выполняется перед тем, как это делают статические или потоковые конструкторы.

...