为什么strcpy_s比strcpy更安全?

Osa*_*imy 1 c string strcpy

当我尝试使用该strcpy功能时,视觉工作室给我一个错误

error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
Run Code Online (Sandbox Code Playgroud)

在网上搜索和 StackOverflow 的许多答案之后,总结是这比将大字符串复制到较短的字符串strcpy_s更安全。strcpy因此,我尝试使用以下代码来处理较短的字符串:

char a[50] = "void";
char b[3];
strcpy_s(b, sizeof(a), a);
printf("String = %s", b);
Run Code Online (Sandbox Code Playgroud)

代码复制成功。但是,仍然存在运行时错误: 在此输入图像描述

那么,怎样才scrcpy_s安全呢?我对安全概念的理解错误吗?

And*_*nle 6

为什么strcpy_s()“更安全”?嗯,它实际上非常复杂。(请注意,此答案忽略了已发布代码中的任何特定代码问题。)

\n

首先,当 MSVC 告诉您诸如strcpy()“已弃用”之类的标准功能时,微软充其量只是不完整。最坏的情况是,微软完全在欺骗你。在这里将您想要的任何动机归因于 Microsoft,但是strcpy()MSVC 称为“已弃用”的许多其他函数是标准 C 函数,并且除了 Microsoft 之外,任何人都肯定不会弃用它们。因此,当 MSVC 警告您某个函数需要在任何符合标准的 C 编译器中实现时(其中大部分会根据要求流入 C++...),它会忽略“由 Microsoft 提供”部分。

\n

微软“有帮助”地建议您使用“更安全”的功能 - 例如,strcpy_s()它们是标准的,因为它们是 C 标准的可选附件 K 的一部分,如果微软按照标准实现它们的话。

\n

根据N1967 - 附件 K \xe2\x80\x94 边界检查接口的现场经验

\n
\n

Microsoft Visual Studio 实现了 API 的早期版本。然而,该实现并不完整,既不符合 C11,也不符合原始 TR 24731-1。例如,它不提供该set_constraint_handler_s函数,而是定义一个_invalid_parameter_handler _set_invalid_parameter_handler(_invalid_parameter_handler)具有类似行为但略有不同且不兼容的签名的函数。它还不定义abort_handler_signore_handler_s函数、memset_s函数(不是 TR 的一部分)或RSIZE_MAX宏。Microsoft 实现也不会将重叠的源序列和目标序列视为运行时约束违规,而是在这种情况下具有未定义的行为。

\n

由于与规范存在大量偏差,因此 Microsoft 的实现不能被认为是一致的或可移植的。

\n
\n

除了少数特定情况(其中strcpy()之一)之外,Microsoft 版本的Annex K 的“更安全”边界检查功能是否更安全是值得商榷的。 根据 N1967(加粗我的):

\n
\n

建议的技术勘误

\n

尽管自最初提案提出已有十多年,自 ISO/IEC TR 24731-1:2007 批准以来已近十年,自将边界检查接口引入 C 标准以来已近五年,但尚未出现可行的符合性实现。API 仍然存在争议,实施者也继续拒绝实施请求。

\n

边界检查接口的设计虽然用意良好,但存在太多需要纠正的问题。人们发现,与依赖现有方法或现代技术相比,使用 API 会导致质量更差、安全性更差的软件。更有效和更少侵入性的方法已经变得司空见惯,并且通常受到用户和安全专家的青睐。

\n

因此,我们建议附件K要么从C标准的下一个修订版中删除,要么弃用然后删除。

\n
\n

但请注意,在 的情况下strcpy()strcpy_s()实际上更类似于strncpy()asstrcpy()只是一个沼泽标准 C 字符串函数,它不执行边界检查,但它strncpy()是一个反常函数,因为它将完全填充其目标缓冲区,从来自源字符串的数据,并用值填充整个目标缓冲区\'\\0\' char除非源字符串填充了整个目标缓冲区,在这种情况下strncpy()不会以\'\\0\' char值终止它。

\n

我将重复一遍: strncpy()不保证正确终止副本。

\n

很难不比“更安全” strncpy()。在这种情况下,并不像那样strcpy_s()违反最小惊讶原则strncpy()。我称之为“更安全”。

\n

但是使用strcpy_s()- 以及所有其他“建议”函数 - 使您的代码实际上不可移植,因为 Microsoft 是任何形式的附件 K 边界检查函数的唯一重要实现。

\n