CRT 中的全局状态
通用 C 运行时 (UCRT) 中的某些函数使用全局状态。 例如,setlocale()
可设置整个程序的区域设置,这会影响数字分隔符、文本代码页等。
UCRT 的全局状态不会在应用程序和 OS 之间共享。 例如,如果应用程序调用 setlocale()
,这不会影响使用 C 运行时的所有 OS 组件的区域设置,反之亦然。
特定于 OS 的 CRT 函数版本
在 UCRT 中,与全局状态交互的函数具有前缀为 _o_
的“孪生”函数。 例如:
setlocale()
影响特定于应用的全局状态。_o_setlocale()
影响所有 OS 组件共享的全局状态,但不影响应用共享的全局状态。
这些“孪生”函数的唯一区别是,当它们读取/写入全局 CRT 状态时,特定于 OS 的版本(即以 _o_
开头的版本)使用 OS 的全局状态副本,而不使用应用的全局状态副本。
这些特定于 OS 的函数版本位于 ucrt.osmode.lib
中。 例如,特定于 OS 的 setlocale()
版本为 _o_setlocale()
可通过两种方法将组件的 CRT 状态与应用的 CRT 状态隔离:
- 使用编译器选项
/MT
(发布)或/MTd
(调试)静态链接组件。 有关详细信息,请参阅 /MD、/MT、/LD。 静态链接会大大增加二进制文件的大小。 - 从 Windows 10 版本 2004 开始的 Windows 版本中,动态链接到 CRT,但调用 OS 模式的导出项(以 o 开头的函数)。 若要调用 OS 模式的导出项,请像以前一样进行静态链接,但使用链接器选项
/NODEFAULTLIB:libucrt.lib
(发布)或/NODEFAULTLIB:libucrtd.lib
(调试)忽略静态 UCRT。 然后将ucrt.osmode.lib
添加到链接器输入。 有关详细信息,请参阅/NODEFAULTLIB
(忽略库)。
注意
在源代码中,写入 setlocale()
,而不是 _o_setlocale()
。 链接 ucrt.osmode.lib
时,链接器将自动替换特定于 OS 的函数版本。 即,setlocale()
将被替换为 _o_setlocale()
。
链接 ucrt.osmode.lib
将禁用某些仅在应用模式下可用的 UCRT 调用。 尝试调用这些函数将导致链接错误。
受应用/OS 隔离影响的全局状态
受应用和 OS 全局状态隔离影响的全局状态包括:
- 区域设置数据
- 由
signal
设置的信号处理程序 - 由
terminate
设置的终止例程 errno
和_doserrno
rand
和srand
使用的随机数生成状态- 返回用户不需要释放的缓冲区的函数:
strtok
、wcstok
、_mbstok
Tmpnam
、_wtmpnam
asctime
、_wasctime
gmtime
、_gmtime32
、_gmtime64
_fcvt
_ecvt
strerror
、_strerror
、_wcserror
、__wcserror
_putch
、_putwch
使用的缓冲区_set_invalid_parameter_handler
、_set_thread_local_invalid_parameter_handler
_set_new_handler
和_set_new_mode
fmode
- 时区信息