CRT 中的安全功能

许多旧 CRT 函数具有更新、更安全的版本。 如果存在安全函数,则较旧的、安全性更低的版本将标记为已弃用,并且新版本具有 _s(“安全”)后缀。

在此上下文中,“已弃用”仅表示不建议使用某个函数;而不表示计划从 CRT 中删除此函数。

安全函数不阻止或纠正安全性错误,而是在出现错误时捕获错误。 它们对错误条件进行附加检查,如果出现错误,它们将调用错误处理程序(请参阅参数验证)。

例如,strcpy 函数无法指明它所复制的字符串对于目标缓冲区是否太大。 但是,它的安全匹配项 strcpy_s 可将缓冲区大小作为参数,以便确定是否将发生缓冲区溢出。 如果您使用 strcpy_s 将 11 个字符复制到 10 字符缓冲区中,那么就是您做错了;strcpy_s 无法纠正您的错误,但它可检测到您的错误,并通过调用无效参数处理程序来告知您此情况。

消除弃用警告

可通过多种方式消除针对较旧的、安全性更低的函数的弃用警告。 最简单的方法是定义 _CRT_SECURE_NO_WARNINGS 或使用警告杂注。 这将禁用弃用警告,但导致出现警告的安全问题仍存在。 更佳的做法是,将弃用警告保持启用状态并利用新的 CRT 安全功能。

在 C++ 中,执行此操作的最简单方法是使用安全模板重载,在许多情况下,它会通过将对已弃用函数的调用替换为对这些函数的新安全版本的调用来消除弃用警告。 例如,考虑此对 strcpy 的已弃用调用:

char szBuf[10];   
strcpy(szBuf, "test"); // warning: deprecated   

_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 定义为 1 可通过将 strcpy 调用更改为 strcpy_s(这将阻止缓冲区溢出)来消除警告。 有关详细信息,请参阅 Secure Template Overloads

对于那些不带安全模板重载的已弃用的函数,你应考虑手动更新代码以使用安全版本。

弃用警告的另一个源(与安全性无关)为 POSIX 函数。 将 POSIX 函数名称替换为它们的标准等效项(例如,将 access 更改为 _access),或通过定义 _CRT_NONSTDC_NO_WARNINGS 来禁用与 POSIX 相关的弃用警告。 有关详细信息,请参阅弃用的 CRT 函数

其他安全功能

一些安全功能包括:

  • Parameter Validation。 在安全函数和许多先前已有的函数版本中验证传递到 CRT 函数的参数。 这些验证包括:

    • 检查已传递到函数的 NULL 值。

    • 检查枚举值的有效性。

    • 检查整数值是否在有效范围内。

  • 有关详细信息,请参阅参数验证

  • 开发人员也可访问无效参数的处理程序。 当遇到无效参数时,CRT 提供使用 _set_invalid_parameter_handler, _set_thread_local_invalid_parameter_handler 函数检查这些问题的方法,而不是断言并退出应用程序。

  • Sized Buffers。 安全函数要求将缓冲区大小传递到对缓冲区进行写入操作的任何函数。 安全版本会在对缓冲区进行写入之前先验证它是否足够大,以帮助避免导致恶意代码能够执行的危险缓冲区溢出错误。 这些函数通常返回一个 errno 类型的错误代码并调用无效参数处理程序(如果缓冲区太小)。 从输入缓冲区读取的函数(如 gets)具有需要您指定最大大小的安全版本。

  • Null termination。 某些可能保留非终止字符串的函数具有安全版本,这将确保字符串以 null 结束。

  • Enhanced error reporting。 安全函数将返回错误代码以及比先前存在的函数返回的错误信息更多的错误信息。 安全函数和许多先前存在的函数现在可设置 errno,并且通常会返回 errno 代码类型,以便提供更好的错误报告。

  • Filesystem security。 默认情况下,安全文件 I/O API 支持安全文件访问。

  • Windows security。 安全进程 API 强制安全策略并允许指定 ACL。

  • Format string syntax checking。 检测到无效字符串,例如,在 printf 格式字符串中使用了不正确的类型字段字符。

另请参阅

参数验证
安全模板重载
CRT 库功能