[英]C++ 'strcpy' gives a Warning (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.
此函数 (strcpy) 被认为是不安全的,因为没有边界检查,并且可能导致缓冲区溢出。 (实际上 strcpy 因溢出漏洞而臭名昭著,所有程序员都避免使用它——或者至少应该避免它)。 建议是使用考虑目标缓冲区大小的安全函数以避免溢出。 您也可以使用 strncpy (但要小心!)。 您的代码没有问题,即函数将按您说的方式运行,但尝试提供一个大于目标缓冲区的缓冲区作为输入。 该函数将溢出目标缓冲区。 检查这也链接文本
虽然 strcpy 是一个常见的字符串函数,但它一直是软件中许多错误和安全漏洞的来源(由于缓冲区溢出很容易)。
微软为了促进更安全的 C 和 C++ 编码,为危险的字符串方法提供了一套替换函数。 通常,它们的原始名称后跟 _s。 因此,根据警告中的建议,strcpy 的 Microsoft 安全版本是 strcpy_s。 请注意,这是 Microsoft 的特定功能,它并非无处不在。
你有几个选择。
我通常做#3。
由于您正在编写 C++,因此正确的解决方案是在可能的情况下从您的代码中禁止 C 风格的char*
字符串,并用std::string
(或其他适当的字符串类型)替换它们。
不要使用功能,如strcpy
或strcpy_s
或strncpy
。 使用string
类的复制构造函数或赋值运算符。 或者,如果您确实需要复制缓冲区,请使用std::copy
。
由于 VC++ 8 strcpy()
和大量其他函数被认为是不安全的,因为它们没有边界检查,如果误用可能会导致缓冲区溢出。
您有两个选择:
_CRT_SECURE_NO_WARNINGS
,这将使警告消失。实际上有一种方法可以避免这个警告,仍然使用 strcpy,并且是安全的:
您可以启用安全模板重载。 他们将(如果可能)通过使用模板化重载捕获它们来推断使用的缓冲区的长度。 为什么在 Visual C++ 中默认情况下没有启用这对我来说是个谜。
该警告基本上是在通知您 strcpy 已被弃用,因为复制字符串直到\\0
很容易导致令人讨厌的问题(缓冲区溢出)。 strcpy 仍然存在并且有效的原因是它是标准库遗留的一部分,但您真的应该考虑使用 str*_s 或 strn* 函数(它们不完全依赖于查找终止\\0
)。
由于缓冲区溢出不仅与安全问题有关,而且与相对难以跟踪和修复的错误有关,因此使用普通的 str* 函数不仅通常不受欢迎,而且可能导致人们拒绝您的代码,因为您的代码本质上是不安全的。
更多详情: http : //www.safercode.com/blog/2008/11/04/unsafe-functions-in-c-and-their-safer-replacements-strings-part-i.html
#pragma warning(disable: 4996)
在代码的第一行使用上面的代码。
如果您已经查看了使用 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 用户的回答......但我找不到引用他/她)
使用安全模板重载或定义包装函数不适用于动态分配的缓冲区,因此这种尝试是徒劳的。
修改源以使用安全替换,或者只是忽略它。
如果代码是自己写的,最好把strcpy改成strcpy_s等。如果模块是从可信源导入的,可以选择忽略警告。
忽略方法1:项目全局范围:添加_CRT_SECURE_NO_WARNINGS
忽略方法 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.