8

어떤 시점에서는 컴파일러가 정적 초기화 시간 동안 실행되는 스레딩 작업을 만들기 위해 특수 코드를 삽입하기 때문에 main()의 첫 번째 줄까지 안전하게 스레드를 작성할 수 없다는 것을 기억합니다. 따라서 건설중인 쓰레드를 생성하는 전역 객체가있는 경우 프로그램이 중단 될 수 있습니다. 하지만 지금은 원본 기사를 찾을 수 없으며 이것이 얼마나 엄격한 제한인지 궁금합니다. 표준에 의해 엄격히 사실입니까? 대부분의 컴파일러에서 사실입니까? C++ 0x에서 그대로 유지됩니까? 표준 준수 컴파일러가 정적 초기화 자체를 다중 스레드로 만들 수 있습니까? (예 : 두 개의 전역 객체가 서로 닿지 않는 것을 감지하고 프로그램 시작을 가속화하기 위해 개별 스레드에서 초기화) 이 점에서, 또는 그것이 의사 표준 인 경우. 예를 들어, 기술적으로 표준은 다른 액세스 지정자 (public/protected/etc.)에 속한 멤버의 레이아웃을 셔플 링 할 수 있습니다. 그러나 내가 실제로 알고있는 컴파일러는 없습니다.정적 초기화 중에 스레드를 안전하게 만들 수 있습니까?

+0

"표준에 엄격히 해당됩니다."- C++ 03 표준은 스레드 주제에 대해 아무 말도하지 않습니다. 현재의 동작을 고려해야 할 곳은 POSIX (물론 표준 * 표준이 아닙니다), MSDN, Boost 또는 컴파일러, 플랫폼 및 스레딩 API에 대한 기타 구현 관련 설명서입니다. 용도. –

답변

6

당신이 말하는 것은 엄격하게 언어가 아니라 C 런타임 라이브러리 (CRT)입니다.
처음에는 Windows에서 CreateThread()과 같은 기본 호출을 사용하여 스레드를 만드는 경우 CRT를 사용하지 않고 곧바로 OS로 이동하기 때문에 원하는 곳이라면 어디서든 할 수 있습니다.
일반적으로 가지고있는 다른 옵션은 CRT의 일부인 _beginthread()을 사용하는 것입니다. 스레드 안전성 errno를 갖는 것과 같이 _beginthread()을 사용하면 몇 가지 장점이 있습니다. Read more about this here. _beginthread()을 사용하여 스레드를 만들려면 _beginthread()에 필요한 초기화가 제대로 수행되지 않았기 때문에 몇 가지 문제가 발생할 수 있습니다.

이것은 정확히 main() 이전에 어떤 순서로 발생하는지에 대한 일반적인 문제를 다룹니다. 기본적으로 Visual Studio로 main() 전에 일어날 필요가있는 모든 것을 처리하는 프로그램의 엔트리 포인트 기능이 있습니다.이 코드는 CRT에있는 코드 조각을 실제로 볼 수 있으며 정확히 무엇이 진행되고 있는지 직접 확인할 수 있습니다. 이 코드를 얻는 가장 쉬운 방법은 코드에서 중단 점을 멈추고 스택 프레임을 살펴 보는 것입니다. main()

+0

감사합니다. MSVC가 설치된 Windows에서 상황이 어떤지 알 수 있습니다. 나는 아직도 다른 플랫폼에 대해 궁금해하지만 실제로 Windows에서 안전한지 아닌지에 대해서는 실제로 대답하지 않는다. (_beginthread()는 아직 초기화되지 않았을 수도있는 초기화에 실제로 의존 하는가?). –

+0

나는 이것을 잘 알고 싶다. 문서에서 언급하지 않는 것 같습니다. – shoosh

2

근본적인 문제는 DllMain에서 수행 할 수있는 작업과 수행 할 수없는 작업에 대한 Windows의 제한 사항입니다. 특히 DllMain에서 스레드를 생성하지 않아도됩니다. 정적 초기화는 종종 DllMain에서 발생합니다. 그런 다음 논리적으로 정적 초기화 중에 스레드를 만들 수 없다는 사실을 알 수 있습니다.

+1

참고 :'프로세스 시작 및 DLL 초기화 루틴 동안 새 스레드를 만들 수 있지만 http://msdn.microsoft.com/에서 프로세스에 대해 DLL 초기화가 완료 될 때까지 실행을 시작하지 않습니다.com/ko-kr/library/ms682453 % 28v = VS.85 % 29.aspx –

+0

공정한 시점에서 보지 못했습니다. 주석은'CreateThread'에 특별히 적용됩니다.'_beginthreadex'에는이 예외가 없습니다. – MSalters

0

C++ 0x/1x 초안을 읽으면 알 수 있듯이 main() 전에 스레드를 시작하는 것이 좋습니다.하지만 여전히 정적 초기화의 일반적인 함정을 따릅니다. 준거하고있는 구현은, thread 생성자가 실행하기 전에, thread가 초기화하는 코드가 실행되도록 (듯이) 할 필요가 있습니다.

관련 문제