安全模板重载Secure Template Overloads

为了支持增强安全机制的版本,Microsoft 已弃用许多 C 运行时库 (CRT) 函数。Microsoft has deprecated many C Runtime library (CRT) functions in favor of security-enhanced versions. 例如,strcpy_sstrcpy 更安全的替代函数。For example, strcpy_s is the more secure replacement for strcpy. 已弃用的函数是安全 bug 的常见来源,因为它们并不阻止可能会覆盖内存的操作。The deprecated functions are common sources of security bugs, because they do not prevent operations that can overwrite memory. 默认情况下,编译器在你使用这些函数之一时生成弃用警告。By default, the compiler produces a deprecation warning when you use one of these functions. CRT 为这些函数提供了 C++ 模板重载,以帮助你轻松地过渡到使用更安全的变体。The CRT provides C++ template overloads for these functions to help ease the transition to the more secure variants.

例如,下面的代码片段生成警告,因为 strcpy 已遭弃用:For example, this code snippet generates a warning because strcpy is deprecated:

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

你会看到弃用警告,提醒你代码可能不安全。The deprecation warning is there to tell you that your code may be unsafe. 如果已验证代码无法覆盖内存,则有多种选择。If you have verified that your code can't overwrite memory, you have several choices. 可以选择忽略弃用警告,也可以在 include 语句之前定义符号 _CRT_SECURE_NO_WARNINGS 以便 CRT 头能够禁用弃用警告,或者将代码更新为使用 strcpy_sYou can choose to ignore the warning, you can define the symbol _CRT_SECURE_NO_WARNINGS before the include statements for the CRT headers to suppress the warning, or you can update your code to use strcpy_s:

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

模板重载提供了其他选择。The template overloads provide additional choices. 如果将 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 定义为 1,则会启用标准 CRT 函数的模板重载,从而自动调用更安全的变体。If you define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES to 1, this enables template overloads of standard CRT functions that call the more secure variants automatically. 如果 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 为 1,则无需更改代码。If _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES is 1, then no changes to your code are necessary. 在后台,对 strcpy 的调用会变成对 strcpy_s 的调用(使用自动提供的大小自变量)。Behind the scenes, the call to strcpy is changed to a call to strcpy_s with the size argument supplied automatically.

#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 不会影响需要使用计数的函数,如 strncpyThe macro _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES does not affect the functions that take a count, such as strncpy. 若要为计数函数启用模板重载,请将 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 定义为 1。To enable template overloads for the count functions, define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT to 1. 但是,在这样做之前,请确保您的代码将传递字符的计数,而不是传递缓冲区的大小(常见错误)。Before doing so, however, make sure that your code passes the count of characters, not the size of the buffer (a common mistake). 此外,如果调用安全变体,则不再需要用来在函数调用之后在缓冲区末尾显式写入一个 null 终止符的代码。Also, code that explicitly writes a null terminator at the end of the buffer after the function call is unnecessary if the secure variant is called. 如果需要截断行为,请参阅 _TRUNCATEIf you need truncation behavior, see _TRUNCATE.

备注

_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 要求 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 也定义为 1。The macro _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT requires that _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES is also defined as 1. 如果将 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 定义为 1 并且将 _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 定义为 0,则应用程序将不会执行任何模板重载。If _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT is defined as 1 and _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES is defined as 0, the application will not perform any template overloads.

_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 定义为 1 后,可启用安全变体(名称以“_s”结尾)的模板重载。When you define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES to 1, it enables template overloads of the secure variants (names ending in "_s"). 在这种情况下,如果 _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 为 1,则必须对原始代码进行一个小更改:In this case, if _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES is 1, then one small change must be made to the original code:

#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1  

// ...  

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

只需要更改函数的名称(添加“_s”);模板重载负责提供大小自变量。Only the name of the function needs to be changed (by adding "_s"); the template overload takes care of providing the size argument.

默认情况下,_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 将定义为 0(已禁用),而且 _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 将定义为 1(已启用)。By default, _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES and _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT are defined as 0 (disabled) and _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES is defined as 1 (enabled).

请注意,这些模板重载只适用于静态数组。Note that these template overloads only work for static arrays. 动态分配的缓冲区需要其他的源代码更改。Dynamically allocated buffers require additional source code changes. 再次查看上面的示例:Revisiting the above examples:

#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");  

以及此示例:And this:

#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");  

请参阅See Also

CRT 中的安全功能 Security Features in the CRT
CRT 库功能CRT Library Features