安全模板重载

为了支持增强安全机制的版本,Microsoft 已弃用许多 C 运行时库 (CRT) 函数。 例如,strcpy_sstrcpy 更安全的替代函数。 已弃用的函数是安全 bug 的常见来源,因为它们并不阻止可能会覆盖内存的操作。 默认情况下,编译器在你使用这些函数之一时生成弃用警告。 CRT 为这些函数提供了 C++ 模板重载,以帮助你轻松地过渡到使用更安全的变体。

例如,下面的代码片段生成警告,因为 strcpy 已遭弃用:

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

你会看到弃用警告,提醒你代码可能不安全。 如果已验证代码无法覆盖内存,则有多种选择。 可以选择忽略弃用警告,也可以在 include 语句之前定义符号 _CRT_SECURE_NO_WARNINGS 以便 CRT 头能够禁用弃用警告,或者将代码更新为使用 strcpy_s

char szBuf[10];  
strcpy_s(szBuf, 10, "test"); // security-enhanced _s function  

模板重载提供了其他选择。 如果将 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 定义为 1,则会启用标准 CRT 函数的模板重载,从而自动调用更安全的变体。 如果 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 为 1,则无需更改代码。 在后台,对 strcpy 的调用会变成对 strcpy_s 的调用(使用自动提供的大小自变量)。

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1  

// ...  

char szBuf[10];  
strcpy(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")  

_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 不会影响需要使用计数的函数,如 strncpy。 若要为计数函数启用模板重载,请将 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 定义为 1。 但是,在这样做之前,请确保您的代码将传递字符的计数,而不是传递缓冲区的大小(常见错误)。 此外,如果调用安全变体,则不再需要用来在函数调用之后在缓冲区末尾显式写入一个 null 终止符的代码。 如果需要截断行为,请参阅 _TRUNCATE

备注

_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 要求 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 也定义为 1。 如果将 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 定义为 1 并且将 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 定义为 0,则应用程序将不会执行任何模板重载。

_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 定义为 1 后,可启用安全变体(名称以“_s”结尾)的模板重载。 在这种情况下,如果 _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 为 1,则必须对原始代码进行一个小更改:

#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1  

// ...  

char szBuf[10];  
strcpy_s(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")  

只需要更改函数的名称(添加“_s”);模板重载负责提供大小自变量。

默认情况下,_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 将定义为 0(已禁用),而且 _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 将定义为 1(已启用)。

请注意,这些模板重载只适用于静态数组。 动态分配的缓冲区需要其他的源代码更改。 再次查看上面的示例:

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1  

// ...  

char *szBuf = (char*)malloc(10);  
strcpy(szBuf, "test"); // still deprecated; you have to change it to  
                       // strcpy_s(szBuf, 10, "test");  

以及此示例:

#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1  

// ...  

char *szBuf = (char*)malloc(10);  
strcpy_s(szBuf, "test"); // doesn't compile; you have to change it to  
                         // strcpy_s(szBuf, 10, "test");  

另请参阅

CRT 中的安全功能
CRT 库功能