C++ C++';strcpy&x27;发出警告(C4996)

C++ C++';strcpy&x27;发出警告(C4996),c++,visual-c++,C++,Visual C++,我收到此警告,但所有功能都正常工作 这到底意味着什么 '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. 此函数(strcpy)被认为是不安全的,因为没有边界检查,可能导致缓冲区溢出。(实际上strcpy因溢出漏洞

我收到此警告,但所有功能都正常工作

这到底意味着什么

'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.
此函数(strcpy)被认为是不安全的,因为没有边界检查,可能导致缓冲区溢出。(实际上strcpy因溢出漏洞而臭名昭著,所有程序员都会避免它,或者至少应该避免它)。建议使用考虑目标缓冲区大小的安全函数,以避免溢出。您也可以使用strncpy(但要小心!)。您的代码没有问题,即函数将按您所说的那样运行,但尝试提供一个大于目标缓冲区的缓冲区作为输入。该函数将使目标缓冲区溢出。同时检查这一点,因为VC++8
strcpy()
和大量其他函数,因为它们没有边界检查,如果使用不当,可能导致缓冲区溢出

您有两个选择:

  • 如果您不确定,请按照VC++所说的做,并使用“安全”函数。它们将触发一个错误处理程序,如果出现问题,它将终止您的程序
  • 如果您知道自己在做什么-您知道不会发生溢出,所有边缘情况都由您的代码处理-在包含CRT头之前定义
    \u CRT\u SECURE\u no\u警告
    ,这将使警告消失

该警告基本上是通知您strcpy已被弃用,因为在
\0
之前复制字符串很容易导致严重问题(缓冲区溢出)。Strucy仍然存在的原因是,它是标准库遗产的一部分,但是您应该真正考虑使用STR*YS或STRN*函数(它不完全依赖于查找终止<代码> \ 0 < /代码>)。 由于缓冲区溢出不仅与安全问题有关,还与相对难以跟踪和修复的错误有关,因此使用普通str*函数不仅通常不受欢迎,而且可能会导致人们因为代码本身不安全而拒绝您的代码

更多详情:

虽然strcpy是一种常见的字符串函数,但它一直是软件中许多错误和安全漏洞的根源(由于缓冲区容易溢出)

微软,为了促进C和C++中的更安全编码,为危险字符串方法提供了一套替换函数。通常情况下,它们的原始名称会以_s结尾。因此,Microsoft安全版本的strcpy是警告中建议的strcpy。请注意,这是Microsoft特有的功能,并非无处不在

你有几个选择

  • 如果您不想在意,请定义“CRT\U安全”警告,以免软件中出现安全问题
  • 用安全的字符串函数替换字符串函数,从而使软件的可移植性降低
  • 包装安全字符串函数并在任何地方使用包装器,在Windows平台上提供增强的安全性,并在其他平台上恢复到传统版本。包装函数可以通过宏或编译函数实现

    我通常做3。

    < P>因为你正在编程C++,正确的解决方法是从代码中禁止C样式<代码> char */COD>字符串,并用“代码> STD::String < /Cube >(或另一个适当的字符串类型)替换它们。
    不要使用诸如
    strcpy
    strcpy\u s
    strncpy
    之类的功能。使用
    字符串
    类的复制构造函数或赋值运算符。或者,如果确实需要复制缓冲区,请使用
    std::copy

    实际上有一种方法可以避免此警告,仍然使用strcpy,并且要安全:

    您可以启用。他们将(如果可能的话)通过使用模板重载捕获缓冲区来推断缓冲区的长度。这是一个谜,为什么我没有在VisualC++中默认启用。 使用或不使用动态分配的缓冲区,因此此尝试是徒劳的。
    要么修改源代码以使用安全替换,要么忽略它

    如果代码是你自己写的,你最好把这个strcpy改成strcpy_等。 如果模块是从受信任的源导入的,则可以选择忽略警告

    忽略方法1:项目全局范围:添加\u CRT\u SECURE\u NO\u警告
    忽略方法2:忽略特定模块:如果只有一个或两个模块,那么在包含这些模块时,您可以简单地对它们发出警告:

    #pragma warning(push)
    #pragma warning(disable: 4996)
    #include <sapi.h>  //legacy module
    #include <sphelper.h> //legacy module
    #pragma warning(pop)
    
    #pragma警告(推送)
    #杂注警告(禁用:4996)
    #包含//遗留模块
    #包含//遗留模块
    #布拉格警告(pop)
    
    > p>如果你已经查看了使用C++纯技术的优点和缺点,而不是担心,因为你知道你的字符串将被终止,那么你也可以禁用MSVC中的警告,这种事情:

    #ifdef _MSC_VER
      // 4231: nonstandard extension used : 'extern' before template explicit instantiation
      // 4250: dominance
      // 4251: member needs to have dll-interface
      // 4275: base needs to have dll-interface
      // 4660: explicitly instantiating a class that's already implicitly instantiated
      // 4661: no suitable definition provided for explicit template instantiation request
      // 4786: identifer was truncated in debug information
      // 4355: 'this' : used in base member initializer list
      // 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
    #   pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910)
    #endif
    
    在代码的第一行使用上述代码

    #pragma once
    #define _CRT_SECURE_NO_WARNINGS 1 
    #define _WINSOCK_DEPRECATED_NO_WARNINGS 1 
    
    在文件的顶端对我有用
    (基于其他SO用户的回答……但我找不到他/她的参考)

    @GMan:编译器不会发出警告“只是为了好玩”。这些警告是有原因的,忽视它们通常是个坏主意。如果编译器已经在告诉你一个问题,你应该认真听。在这种情况下,它是一个关于潜在安全问题的警告(或者只是一个潜在的崩溃源),并要求您使用一个更合理的函数。@DarkDust:除了我不会(!)使用
    strcpy
    (或者
    strcpy\u
    )之外,使用正常的C函数是完全正确的,使用“安全”函数CRT的变种只会给人一种安全的错觉,仅此而已。更重要的是,它们是不可移植的。@DarkDust:我相信这种警告对于那些通常不太关心字符串边界的初学者或懒惰的编程人员是有用的。如果您确实知道您有一个以NULL结尾的字符串(不是来自用户输入),我不明白为什么我们应该避免使用完美工作
    #pragma once
    #define _CRT_SECURE_NO_WARNINGS 1 
    #define _WINSOCK_DEPRECATED_NO_WARNINGS 1