简体   繁体   English

C++ 'strcpy' 发出警告 (C4996)

[英]C++ 'strcpy' gives a Warning (C4996)

I am getting this warning but all functions working properly .我收到此警告,但所有功能都正常工作。

what does this really means?这到底是什么意思?

'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.

This function (strcpy) is considered unsafe due to the fact that there is no bounds checking and can lead to buffer overflow.此函数 (strcpy) 被认为是不安全的,因为没有边界检查,并且可能导致缓冲区溢出。 (Actually strcpy is infamous for overflow exploits and all programmers avoid it-or at least should avoid it). (实际上 strcpy 因溢出漏洞而臭名昭著,所有程序员都避免使用它——或者至少应该避免它)。 The advice is to use a safe function which takes into account the size of the destination buffer to avoid overflow.建议是使用考虑目标缓冲区大小的安全函数以避免溢出。 You could also use strncpy (BUT with caution!).您也可以使用 strncpy (但要小心!)。 There is no problem with your code, ie the functions will run as you say but try giving as input a buffer that is larger than the destination buffer.您的代码没有问题,即函数将按您说的方式运行,但尝试提供一个大于目标缓冲区的缓冲区作为输入。 The function will overflow the destination buffer.该函数将溢出目标缓冲区。 Check this also link text检查这也链接文本

While strcpy is a common string function, it has a history of being the source of many bugs and security holes in software (due to the ease of buffer overflows).虽然 strcpy 是一个常见的字符串函数,但它一直是软件中许多错误和安全漏洞的来源(由于缓冲区溢出很容易)。

Microsoft, in an effort to promote safer coding in C and C++ has provided a suite of replacement functions for the dangerous string methods.微软为了促进更安全的 C 和 C++ 编码,为危险的字符串方法提供了一套替换函数。 Typically they have the original name postpended with _s.通常,它们的原始名称后跟 _s。 Hence the Microsoft secure version of strcpy is strcpy_s as recommended in the warning.因此,根据警告中的建议,strcpy 的 Microsoft 安全版本是 strcpy_s。 Note this a Microsoft specific feature, it's not ubiquitious.请注意,这是 Microsoft 的特定功能,它并非无处不在。

You've got a few options.你有几个选择。

  1. DEFINE _CRT_SECURE_NO_WARNINGS if you don't want to care about it, leaving the possibility of the security issues in your software. DEFINE _CRT_SECURE_NO_WARNINGS 如果你不想关心它,就会在你的软件中留下安全问题的可能性。
  2. Replace your string functions with the secure ones, leaving your software less portable as a consequence用安全的函数替换您的字符串函数,从而使您的软件可移植性降低
  3. Wrap the secure string functions and use the wrappers everywhere, providing enhanced security on Windows platforms, and falling back to the traditional versions on other platforms.包装安全字符串函数并在任何地方使用包装器,在 Windows 平台上提供增强的安全性,并在其他平台上回退到传统版本。 The wrapper functions could be via a MACRO or compiled functions.包装函数可以通过宏或编译函数。

I typically do #3.我通常做#3。

Since you're programming C++, the correct solution is to ban C-style char* strings from your code where possible, and replace them by std::string (or another appropriate string type).由于您正在编写 C++,因此正确的解决方案是在可能的情况下从您的代码中禁止 C 风格的char*字符串,并用std::string (或其他适当的字符串类型)替换它们。

Do not use functions such as strcpy or strcpy_s or strncpy .不要使用功能,如strcpystrcpy_sstrncpy Use the copy constructor or assignment operator of the string class.使用string类的复制构造函数或赋值运算符。 Or if you really need to copy buffers, use std::copy .或者,如果您确实需要复制缓冲区,请使用std::copy

Since VC++ 8 strcpy() and a huge set of other functions are considered to be unsafe since they don't have bounds checking and can lead to a buffer overrun if misused.由于 VC++ 8 strcpy()和大量其他函数被认为是不安全的,因为它们没有边界检查,如果误用可能会导致缓冲区溢出。

You have two options:您有两个选择:

  • if you're unsure - do what VC++ says and use "safe" functions.如果您不确定 - 执行 VC++ 所说的并使用“安全”功能。 They will trigger an error handler that will terminate your program if something goes wrong.如果出现问题,它们将触发一个错误处理程序,该处理程序将终止您的程序。
  • if you know what you're doing - you know that no overrun will ever occur and all edge cases are handled by your code - define _CRT_SECURE_NO_WARNINGS prior to including CRT headers and this will make the warning go away.如果您知道自己在做什么 - 您知道永远不会发生溢出并且所有边缘情况都由您的代码处理 - 在包含 CRT 标头之前定义_CRT_SECURE_NO_WARNINGS ,这将使警告消失。

There is actualy a way to avoid this warning, still use strcpy, and be safe:实际上有一种方法可以避免这个警告,仍然使用 strcpy,并且是安全的:

You can enable the secure template overloads .您可以启用安全模板重载 They will (if possible) deduce the lengths of the buffers used by capturing them with templated overloads.他们将(如果可能)通过使用模板化重载捕获它们来推断使用的缓冲区的长度。 It's a mystery to me why this is not enabled by default in Visual C++.为什么在 Visual C++ 中默认情况下没有启用这对我来说是个谜。

That warning is basically informing you that strcpy is deprecated, because copying a string until \\0 can easily lead to nasty problems (buffer overruns).该警告基本上是在通知您 strcpy 已被弃用,因为复制字符串直到\\0很容易导致令人讨厌的问题(缓冲区溢出)。 The reason strcpy is still there and works is that it is part of the standard library legacy, but you should really consider using str*_s or strn* functions (which don't exclusively rely on finding the terminating \\0 ). strcpy 仍然存在并且有效的原因是它是标准库遗留的一部分,但您真的应该考虑使用 str*_s 或 strn* 函数(它们不完全依赖于查找终止\\0 )。

Since buffer overruns are linked not only to security problems, but also to bugs which are relatively difficult to trace and fix, using plain vanilla str* functions is not only generally frowned upon, but can lead to people rejecting your code as inherently unsafe.由于缓冲区溢出不仅与安全问题有关,而且与相对难以跟踪和修复的错误有关,因此使用普通的 str* 函数不仅通常不受欢迎,而且可能导致人们拒绝您的代码,因为您的代码本质上是不安全的。

More details: http://www.safercode.com/blog/2008/11/04/unsafe-functions-in-c-and-their-safer-replacements-strings-part-i.html更多详情: http : //www.safercode.com/blog/2008/11/04/unsafe-functions-in-c-and-their-safer-replacements-strings-part-i.html

#pragma warning(disable: 4996)

在代码的第一行使用上面的代码。

If you have looked at the pros and cons of using C++ purist technique vs. not worrying because you 'know' your strings will be zero terminated, then you can also disable the warning in msvc, this sort of thing:如果您已经查看了使用 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 

at the top of the file worked for me (based on other SO user's answer... but I couldn't find to ref him/her)在文件的顶部为我工作(基于其他 SO 用户的回答......但我找不到引用他/她)

use Secure Template Overloads or define wrapper functions not work for dynamically allocated buffers, so this attempt is futile.使用安全模板重载定义包装函数不适用于动态分配的缓冲区,因此这种尝试是徒劳的。
Either modify source to use secure replacement, or just ignore it.修改源以使用安全替换,或者只是忽略它。

if the codes are writing by yourself, you had better change such strcpy to strcpy_s etc. if the modules are imported from trusted soures, you may choose to ignore the warning.如果代码是自己写的,最好把strcpy改成strcpy_s等。如果模块是从可信源导入的,可以选择忽略警告。

ignore method 1: project globle scope: add _CRT_SECURE_NO_WARNINGS忽略方法1:项目全局范围:添加_CRT_SECURE_NO_WARNINGS
ignore method 2: ignore particular module: if only one or two of them, then you could simplely forbit warning for these modules when include them:忽略方法 2:忽略特定模块:如果只有其中一两个,那么您可以在包含这些模块时简单地禁止警告:

#pragma warning(push)
#pragma warning(disable: 4996)
#include <sapi.h>  //legacy module
#include <sphelper.h> //legacy module
#pragma warning(pop)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM