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

我在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警告?

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

您收到警告,因为Visual Studio很糟糕。 看到这个 。

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

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

什么strcpy做和不做:

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

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

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

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

如果缺少终止NULstrcpy是不安全的,因为它可能会复制比目标区域中更多的字符。 使用memcpy ,复制的字节数是固定的。

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

您收到这些警告是因为没有传递字符串的长度并且依赖于\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等替代方法

包含在头文件"stdafx.h"

 #define _CRT_SECURE_NO_WARNINGS 

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

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

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

该警告表明该函数已弃用且将来版本不可用: http : //msdn.microsoft.com/en-US/en-en/library/ttcz0bys.aspx您无法在弃用时添加其他函数微软的名单。

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

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

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

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