strncpy_s不尊重标准?
strncpy_s does not respect the standard?
我的代码在 Visual Studio 2010 上运行良好:
std::string s = "Ceci est le test du StrnCpy";
char buffer_standard[5];
strncpy( buffer_standard, s.c_str(), 5 );
assert( strncmp( buffer_standard, "Ceci ", 5 ) == 0 );
但是,编译器报告 strncpy 不安全,因为我不想设置 _CRT_SECURE_NO_WARNINGS(因为它们可能是正确的,不安全),我尝试使用 MSDN strncpy_s 版本. 但它的行为方式不同!!!
- 第一个区别:
这会引发断言(缓冲区太小),因此您必须调整大小参数:
std::string s = "Ceci est le test du StrnCpy";
char buffer_msdn[5];
strncpy_s( buffer_msdn, s.c_str(), 5 );
所以我尝试了这个,但是 buffer_msdn[4] 是 '\0' 而不是 ' ':
std::string s = "Ceci est le test du StrnCpy";
char buffer_msdn[5];
strncpy_s( buffer_msdn, s.c_str(), 5-1 );
assert( strncmp( buffer_msdn, "Ceci ", 5 ) == 0 ); // asserts!
这同样失败了:
strncpy_s( buffer_msdn, sc.c_str(), _TRUNCATE );
- 二差:
额外字符的处理方式不同:
std::string s = "Ceci";
char buffer_standard[20];
strncpy( buffer_standard, s.c_str(), 20 );
char buffer_msdn[20];
strncpy_s( buffer_msdn, s.c_str(), s.size() );
buffer_standard
是 "Ceci" 后跟 16 '\0'
buffer_msdn
是"Ceci"后面只有一个'\0'(那就是垃圾)
那么,Microsoft 如何期望我们用 strncpy_s 替换具有相同行为的 strncpy???
how does Microsoft expects us to replace strncpy
by strncpy_s
with the same behaviour?
如果他们有相同的行为,他们将不可避免地遇到相同的安全问题:可能无法终止。 strncpy
接受的参数优先于 NUL
终止复制更多源数据,新功能基本上考虑了该选择对保证警告提示很重要的情况:
- 代码更改为:
- 显示程序员对少复制一个源字符感到高兴,或者,
- 调整目标缓冲区的大小以接受额外的字符,否则
- 移动到另一个函数,例如
memcpy
(可能需要额外事先调用 strlen()
或 .size()
)或坚持使用 strncpy
(可能使用 _CRT_SECURE_NO_WARNINGS
).
由于这些函数专门支持 ASCIIZ 字符串 - 其中仅要求一个尾随 NUL
- 偶尔使用最后一个选项的不便显然被认为是可以接受的。
我的代码在 Visual Studio 2010 上运行良好:
std::string s = "Ceci est le test du StrnCpy";
char buffer_standard[5];
strncpy( buffer_standard, s.c_str(), 5 );
assert( strncmp( buffer_standard, "Ceci ", 5 ) == 0 );
但是,编译器报告 strncpy 不安全,因为我不想设置 _CRT_SECURE_NO_WARNINGS(因为它们可能是正确的,不安全),我尝试使用 MSDN strncpy_s 版本. 但它的行为方式不同!!!
- 第一个区别:
这会引发断言(缓冲区太小),因此您必须调整大小参数:
std::string s = "Ceci est le test du StrnCpy";
char buffer_msdn[5];
strncpy_s( buffer_msdn, s.c_str(), 5 );
所以我尝试了这个,但是 buffer_msdn[4] 是 '\0' 而不是 ' ':
std::string s = "Ceci est le test du StrnCpy";
char buffer_msdn[5];
strncpy_s( buffer_msdn, s.c_str(), 5-1 );
assert( strncmp( buffer_msdn, "Ceci ", 5 ) == 0 ); // asserts!
这同样失败了:
strncpy_s( buffer_msdn, sc.c_str(), _TRUNCATE );
- 二差:
额外字符的处理方式不同:
std::string s = "Ceci";
char buffer_standard[20];
strncpy( buffer_standard, s.c_str(), 20 );
char buffer_msdn[20];
strncpy_s( buffer_msdn, s.c_str(), s.size() );
buffer_standard
是 "Ceci" 后跟 16 '\0'
buffer_msdn
是"Ceci"后面只有一个'\0'(那就是垃圾)
那么,Microsoft 如何期望我们用 strncpy_s 替换具有相同行为的 strncpy???
how does Microsoft expects us to replace
strncpy
bystrncpy_s
with the same behaviour?
如果他们有相同的行为,他们将不可避免地遇到相同的安全问题:可能无法终止。 strncpy
接受的参数优先于 NUL
终止复制更多源数据,新功能基本上考虑了该选择对保证警告提示很重要的情况:
- 代码更改为:
- 显示程序员对少复制一个源字符感到高兴,或者,
- 调整目标缓冲区的大小以接受额外的字符,否则
- 移动到另一个函数,例如
memcpy
(可能需要额外事先调用strlen()
或.size()
)或坚持使用strncpy
(可能使用_CRT_SECURE_NO_WARNINGS
).
由于这些函数专门支持 ASCIIZ 字符串 - 其中仅要求一个尾随 NUL
- 偶尔使用最后一个选项的不便显然被认为是可以接受的。