8

在某些时候,我记得读到在 main() 的第一行之前无法安全地创建线程,因为编译器插入特殊代码以使线程在静态初始化期间运行。因此,如果您有一个在构造时创建线程的全局对象,您的程序可能会崩溃。但是现在我找不到原始文章了,我很好奇这是一个多么严格的限制——按标准严格来说是真的吗?大多数编译器都是这样吗?在 C++0x 中它会保持不变吗?符合标准的编译器是否可以使静态初始化本身成为多线程的?(例如检测两个全局对象不相互接触,并在单独的线程上初始化它们以加速程序启动)

编辑:为了澄清,我试图至少了解实现在这方面是否真的有很大差异,或者它是否是伪标准的东西。例如,从技术上讲,该标准允许改组属于不同访问说明符(公共/受保护/等)的成员的布局。但是我所知道的编译器实际上没有这样做。

4

3 回答 3

6

您所说的不是严格意义上的语言,而是 C 运行时库 (CRT)。
首先,如果您使用本机调用(例如CreateThread()在 Windows 上)创建线程,那么您可以在任何您想要的地方进行操作,因为它直接进入操作系统,无需 CRT 干预。
您通常拥有的另一个选项是使用_beginthread()CRT 的一部分。使用有一些优点,_beginthread()例如具有线程安全的 errno。在此处阅读有关此内容的更多信息。如果您要创建线程 using_beginthread()可能会出现一些问题,因为所需的初始化_beginthread()可能没有到位。

这涉及到一个更普遍的问题,即之前究竟发生了什么main()以及以什么顺序发生。基本上,您拥有程序的入口点功能,该功能负责使用 Visual Studio 之前需要发生的所有事情,main()您实际上可以查看 CRT 中的这段代码,并亲自了解那里到底发生了什么。获取该代码的最简单方法是在代码中停止断点并查看之前的堆栈帧main()

于 2009-09-18T15:23:37.810 回答
2

根本问题是 Windows 对您在 DllMain 中可以做什么和不可以做什么的限制。特别是,您不应该在 DllMain 中创建线程。静态初始化通常发生在 DllMain。然后从逻辑上讲,您不能在静态初始化期间创建线程。

于 2009-09-21T11:36:04.163 回答
0

据我从阅读 C++0x/1x 草案中可以看出,在此之前启动一个线程main()很好,但仍然受到静态初始化的正常陷阱的影响。符合要求的实现必须确保初始化线程的代码在任何静态或线程构造函数之前执行。

于 2009-09-22T20:50:28.383 回答