strncpy_s不尊重标准?

时间:2015-03-30 08:21:01

标签: c++ strncpy

我使用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版本。 但它的行为方式不一样!!!

  • 第一个区别:

这会引发一个断言(缓冲区太小),所以你必须调整size参数:

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具有相同的行为?

1 个答案:

答案 0 :(得分:1)

  

Microsoft希望我们以strncpy替换strncpy_s具有相同的行为?

如果他们有相同的行为,他们就不可避免地会遇到同样的安全问题:可能缺乏终止。 strncpy接受的参数预先通过NUL终止复制更多源数据,新功能基本上考虑了这种选择对于需要警告提示的重要情况:

  • 代码更改为:
    • 表示程序员很乐意为一个较少的源字符复制或
    • 调整目标缓冲区的大小以接受额外的字符,否则
  • 转移到另一个功能,例如memcpy(可能需要额外事先致电strlen().size())或坚持strncpy(可能与_CRT_SECURE_NO_WARNINGS }})。

由于这些功能特别支持ASCIIZ字符串 - 其中只有一个尾随NUL是强制性的 - 偶尔使用最后一个选项的不便显然被认为是可接受的。