C4996(函数unsafe)警告strcpy但不是memcpy

时间:2014-05-06 05:56:53

标签: c visual-studio-2010

我在VS2010中编写代码,我碰巧在编译后看到编译器为strcpy和sprintf调用提供了C4996警告(“此函数或变量可能不安全”)。

但是,我无法获得memcpy的类似警告(并且可能在代码中有更多类似的'不安全'函数调用)

int _tmain(int argc, _TCHAR* argv[])
{
    char buf1[100], buf2[100];
    strcpy (buf1, buf2); // Warning C4996 displayed here asking to use strcpy_s instead
    memcpy (buf1, buf2, 100); // No warning here asking to use memcpy_s
    memcpy_s(buf1, 100, buf2, 100);
    return 0;
}

为什么会这样?如何在我的代码中为所有可能的不安全呼叫打开C4996警告?

7 个答案:

答案 0 :(得分:17)

通常,要编译C代码,您需要一个符合C的编译器。 Visual Studio是一个不合格的C ++编译器。

您收到警告,因为Visual Studio很糟糕。 See this

只要您使用Microsoft认为过时的功能,就会出现

C4996。显然,微软决定他们应该决定C语言的未来,而不是ISO C工作组。因此,您会得到错误的警告以获得完美的代码。编译器就是问题所在。

strcpy()函数没有任何问题,这是一个神话。这个功能已经存在了大约30 - 40年,每一点都有适当的记录。因此,即使对于初学者C程序员来说,该功能的功能和功能也不应该让人感到意外。

strcpy做什么和不做什么:

  • 它将以空字符结尾的字符串复制到另一个内存位置。
  • 对错误处理不承担任何责任。
  • 它不会修复调用者应用程序中的错误。
  • 教育C程序员不承担任何责任。

由于上面的最后一句话,在调用strcpy之前必须知道以下内容:

  • 如果您将未知长度的字符串传递给strcpy,而不事先检查其长度,则调用者应用程序中存在错误。
  • 如果您传递了一些不以\0结尾的数据,则调用者应用程序中存在错误。
  • 如果传递两个指向strcpy()的指针,指向重叠的内存位置,则调用未定义的行为。这意味着你在调用者应用程序中有一个错误。

例如,在您发布的代码中,您从未初始化数组,因此您的程序可能会崩溃并烧毁。这个bug与strcpy()函数没有丝毫相关,也不会通过替换strcpy()来解决。

答案 1 :(得分:6)

如果缺少终止strcpy,则

NUL不安全,因为它可能会复制比目标区域更多的字符。使用memcpy,复制的字节数是固定的。

memcpy_s函数实际上让程序员更容易做错 - 你传递了两个长度,它使用两者中较小的一个,你得到的只是一个错误代码,可以默默地忽略努力。调用memcpy需要填写size参数,这应该让程序员考虑要传递的内容。

答案 2 :(得分:1)

您收到这些警告是因为没有传递字符串的长度并依赖\0终止是不安全的,因为它们可能导致缓冲区溢出。在memcpy中你传递长度所以没有溢出问题。

您可以使用类似

的内容
#ifdef _MSC_VER
#  pragma warning(push)
#  pragma warning(disable:4996)
#endif
strcpy... ;  // Code that causes unsafe warning
#ifdef _MSC_VER
#  pragma warning(pop)
#endif

如果您不担心可移植性,可以使用strcpy_s等替代方法

答案 3 :(得分:1)

包含在标题"stdafx.h"定义

#define _CRT_SECURE_NO_WARNINGS

至于strcpymemcpy的差异,那么最后一个函数有第三个参数,它明确指定必须复制多少个字符。第一个函数没有信息将从源字符串复制到目标字符串的字符数,因此通常情况下,可能会覆盖为目标字符串分配的内存。

答案 4 :(得分:0)

因为strcpysprintf确实是不安全的函数,所以它取决于字符串的内容不会溢出。相反,您应该使用strncpysnprintf来确保它不会覆盖内存。

虽然memcpy不是这种情况,但它具有长度,因此只要长度正确,它就不会覆盖内存。

答案 5 :(得分:0)

该警告表示该函数已弃用且在将来的版本中不可用:http://msdn.microsoft.com/en-US/en-en/library/ttcz0bys.aspx您无法将其他函数添加到Microsoft的弃用列表中。

弃用的原因是“不安全”,但这与您的假设“C4496向您显示所有不安全的功能”不同。

答案 6 :(得分:0)

您在sprintfstrcpy而不是memcpy上收到警告的原因是因为memcpy的长度参数限制了您复制的内存量。对于strcpymemcpy,输入必须以\0终止。如果没有,它将继续超出范围。您可以使用snprintfstrncpy函数来限制此操作。那些可以隐含地限制可以复制多少。

请注意,Microsoft已弃用snprintf,因此您应该使用替换函数_snprintf。但是,这是MSVC特定的功能。

我建议一起取消char *个缓冲区并使用stl容器切换到C ++,例如std::string。这些将为您节省大量的调试麻烦并保持代码的可移植性。