在某些时候我记得读过在main()的第一行之前无法安全地创建线程,因为编译器会插入特殊代码来使线程在静态初始化时运行。因此,如果您有一个在构造时创建线程的全局对象,您的程序可能会崩溃。但是现在我找不到原始文章了,我很好奇这是一个多么强烈的限制 - 标准是否严格如此?大多数编译器都是如此吗?它会在C ++ 0x中保持真实吗?符合标准的编译器是否有可能使静态初始化本身多线程? (例如,检测到两个全局对象不会彼此接触,并在不同的线程上初始化它们以加速程序启动)
编辑:为了澄清,我试图至少了解实现在这方面是否真的有很大不同,或者它是否是伪标准的东西。例如,从技术上讲,该标准允许改组属于不同访问说明符(public / protected / etc.)的成员的布局。但我知道的编译器实际上没有这样做。
答案 0 :(得分:6)
您所说的并非严格使用语言,而是使用C运行时库(CRT)
首先,如果您在Windows上使用本机调用(例如CreateThread()
)创建一个线程,那么您可以在任何您喜欢的地方执行此操作,因为它直接进入操作系统而无需CRT干预。
您通常使用的另一个选项是使用_beginthread()
,这是CRT的一部分。使用_beginthread()
有一些优点,例如具有线程安全的错误。 Read more about this here。如果您要使用_beginthread()
创建线程,可能会出现一些问题,因为_beginthread()
所需的初始化可能不会到位。
这触及了一个更为一般性的问题,即main()
之前到底发生了什么,以及顺序是什么。基本上你有程序的入口点函数来处理在使用Visual Studio main()
之前需要发生的所有事情,你可以实际查看CRT中的这段代码并自己找出那里到底发生了什么。获得该代码的最简单方法是在代码中停止断点并查看main()
之前的堆栈帧
答案 1 :(得分:2)
根本问题是Windows限制你在DllMain中可以做什么和不能做什么。特别是,你不应该在DllMain中创建线程。静态初始化通常发生在DllMain上。然后逻辑上遵循在静态初始化期间无法创建线程。
答案 2 :(得分:0)
据我所知,通过阅读C ++ 0x / 1x草案,在main()
之前启动一个线程很好,但仍然存在静态初始化的常见缺陷。符合条件的实现必须确保在任何静态或线程构造函数之前执行初始化线程的代码。