/Zc:threadSafeInit 编译器选项告知编译器以线程安全的方式初始化静态局部(函数范围)变量,从而无需手动同步。 只有初始化是线程安全的。 多个线程对静态局部变量的使用和修改仍然必须手动同步。 此选项自 Visual Studio 2015 起可用。 Visual Studio 默认启用此选项。

/Zc:threadSafeInit[ - ]

在 C++11 标准中,具有静态或线程存储持续时间的块范围变量必须在进行任何其他初始化之前进行零初始化。 在控件第一次通过变量的声明时进行初始化。 如果在初始化期间抛出异常,则认为该变量未初始化,并且在下一次控制通过声明时重新尝试初始化。 如果控制与初始化同时进入声明,则在初始化完成时并发执行阻塞。 如果控件在初始化期间递归地重新进入声明,则行为未定义。 默认情况下,从 Visual Studio 2015 开始的 Visual Studio 实现此标准行为。 可以通过设置 /Zc:threadSafeInit 编译器选项显式指定此行为。

/Zc:threadSafeInit 编译器选项默认开启。 /permissive- 选项不影响 /Zc:threadSafeInit。

静态局部变量的线程安全初始化依赖于通用 C 运行时库 (UCRT) 中实现的代码。 若要避免依赖 UCRT,或保留 Visual Studio 2015 之前版本的 Visual Studio 的非线程安全初始化行为,请使用 /Zc:threadSafeInit- 选项。 如果你知道不需要线程安全,请使用此选项围绕静态局部声明生成更小、更快的代码。

线程安全的静态局部变量在内部使用线程局部存储 (TLS) 以在静态已经初始化时提供高效执行。 此功能的实现依赖于 Windows Vista 及更高版本操作系统中的 Windows 操作系统支持功能。 Windows XP、Windows Server 2003 和较旧的操作系统没有此支持,因此它们得不到效率优势。 这些操作系统对可以加载的 TLS 节的数量也规定了下限。 超出 TLS 节限制可能会导致崩溃。 如果是你的代码出现问题,尤其是必须在旧操作系统上运行的代码中,请使用 /Zc:threadSafeInit- 禁用线程安全初始化代码。

有关 Visual C++ 中一致性问题的详细信息,请参阅 Nonstandard Behavior

在 Visual Studio 开发环境中设置此编译器选项

  • 打开项目的“属性页” 对话框。 有关详细信息,请参阅 在 Visual Studio 中设置 C++ 编译器和生成属性

  • 从“配置”下拉菜单中,选择“所有配置”。

  • 选择“配置属性”>“C/C++”>“命令行”属性页。

  • 修改 Additional Options 属性以包括 /Zc:threadSafeInit 或 /Zc:threadSafeInit-,然后选择“确定”。

    MSVC 编译器选项
    MSVC 编译器命令行语法
    /Zc(一致性)

  •