8

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

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

+0

«это строго верно по стандарту» - стандарт C++ 03 не имеет права говорить по теме потоков. Места, чтобы посмотреть, что касается текущего поведения, будет POSIX (который, конечно, * стандартный *, а не * * стандартный), MSDN, Boost или другие документы для конкретной реализации для API компилятора, платформы и потоков использовать. –

ответ

6

Что вы говорите, это не строго на языке, а в библиотеке времени выполнения C (CRT).
Для начала, если вы создаете поток, используя собственный вызов, такой как CreateThread() на окнах, тогда вы можете делать это в любом месте, потому что оно идет прямо к ОС без вмешательства ЭЛТ.
Другой вариант, который вы обычно используете, заключается в использовании _beginthread(), который является частью ЭЛТ. Существуют некоторые преимущества использования _beginthread(), например, с защитой от потоков. Read more about this here. Если вы собираетесь создавать потоки с использованием _beginthread(), могут возникнуть некоторые проблемы, поскольку инициализации, необходимые для _beginthread(), могут быть не на месте.

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

+0

Спасибо, это дает мне некоторое представление о том, что такое ситуация на Windows с MSVC. Мне все еще интересно узнать о других платформах, но на самом деле он не отвечает, безопасно ли это в Windows или нет (действительно ли _beginthread() полагается на любую инициализацию, которая, возможно, еще не состоялась?). –

+0

Хотел бы я знать это. Документы, похоже, не упоминают об этом. – shoosh

2

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

+1

Но обратите внимание: 'Во время запуска процесса и инициализации DLL новые потоки могут быть созданы, но они не запускаются до тех пор, пока для процесса не будет выполнена инициализация DLL' с http://msdn.microsoft.com/en-us/library/ms682453% 28v = VS.85% 29.aspx –

+0

Справедливая точка, не заметила этого. Обратите внимание, что комментарий применяется специально к 'CreateThread', хотя' _beginthreadex' не имеет этого исключения. – MSalters

0

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