C++ 如何摆脱 Visual Studio 中的“不安全”警告/错误(strcpy、sprintf、strdup)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3327000/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get rid of "unsafe" warnings / errors in Visual Studio (strcpy, sprintf, strdup)
提问by Andre
I'm trying to get rid of some compiler warnings that say strcpy, sprintf, etc are unsafe. I get why they're unsafe, but I can't think of a good way to fix the code, in a C++ style.
我试图摆脱一些编译器警告,这些警告说 strcpy、sprintf 等不安全。我明白为什么它们不安全,但我想不出用 C++ 风格修复代码的好方法。
Here's a excerpt of the code:
这是代码的摘录:
extList->names[i]=(char *)malloc(length*sizeof(char));
strcpy(extList->names[i],extName); // unsafe
// strncpy(extList->names[i],extName,length); // also unsafe
Here's the message:
这是消息:
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.
C4996:'strcpy':此函数或变量可能不安全。考虑使用 strcpy_s 代替。要禁用弃用,请使用 _CRT_SECURE_NO_WARNINGS。详细信息请参见在线帮助。
I can't think of a safe way to copy the data over in C++ without knowing the length of the stuff to copy. I know there's strlen(), but that's also unsafe since it assumes (maybe incorrectly) that the data is null-terminated.
在不知道要复制的内容的长度的情况下,我想不出一种在 C++ 中复制数据的安全方法。我知道有 strlen(),但这也是不安全的,因为它假定(可能不正确)数据以空字符结尾。
Also:
还:
// used to concatenate:
sprintf(extStr,"%s%s",platExtStr,glExtStr);
C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
C4996:'sprintf':此函数或变量可能不安全。考虑使用 sprintf_s 代替。要禁用弃用,请使用 _CRT_SECURE_NO_WARNINGS。详细信息请参见在线帮助。
Using std::string to concatenate is easy enough, but then I need to get the data into extStr somehow (and not using strcpy, lol). The string::c_str() function returns a pointer to un-modifiable data, so I can't just set extStr equal to it. (And I'm not even sure if the c_str() pointer needs delete called on it later? Does it allocate space using "new"?)
使用 std::string 连接很容易,但是我需要以某种方式将数据放入 extStr (而不是使用 strcpy,哈哈)。string::c_str() 函数返回一个指向不可修改数据的指针,所以我不能只是将 extStr 设置为等于它。(我什至不确定 c_str() 指针是否需要稍后调用 delete ?它是否使用“new”分配空间?)
Any advice on this stuff? This is part of a 10,000 line file that's not mine... so I'm not exactly keen on re-writing the thing in the C++ way.
关于这个东西有什么建议吗?这是一个 10,000 行文件的一部分,它不是我的……所以我并不热衷于用 C++ 方式重写这个东西。
回答by SigTerm
You don't really need pragmas to disable them.
你真的不需要编译指示来禁用它们。
For win32/msvc, in ProjectProperties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions, add following macros:
对于 win32/msvc,在 ProjectProperties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions 中,添加以下宏:
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
Or you can pass thos in command line parameters (-D_CRT_SECURE_NO_DEPRECATE). You can probably #define them at the beginning of certain *.cpp files. Also, there are probably more of them (see crtdefs.h - looks like there are a lot of them...). Those kind of warnings normally tell you with which macros you can disable them - just read compiler output.
或者您可以在命令行参数中传递 thos (-D_CRT_SECURE_NO_DEPRECATE)。您可以在某些 *.cpp 文件的开头 #define 它们。此外,可能还有更多(参见 crtdefs.h - 看起来有很多......)。这类警告通常会告诉您可以使用哪些宏禁用它们 - 只需阅读编译器输出。
回答by PapaAtHome
Here is another answer to this question.
这是这个问题的另一个答案。
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
strcpy(destination, source);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
回答by V M Rakesh
If getting rid of warnings only is your objective... simply define this _CRT_SECURE_NO_WARNINGS
and it will suppress all the deprecation warnings. But this will not fix the underlying problems with unsafe CRT functions.
如果您的目标只是摆脱警告......只需定义 _CRT_SECURE_NO_WARNINGS
它,它将抑制所有弃用警告。但这不会解决不安全 CRT 函数的潜在问题。
If you are on visual studio version >= 2005 and want to fix these warnings in a proper way... easiest method is to #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
and #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
in your project.
如果你在Visual Studio的版本> = 2005,并希望以适当的方式来解决这些警告......最简单的方法就是#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
和#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
你的项目。
without any further code changes you can observe most of the warnings are fixed automatically. By defining this windows will automatically call the secure overloaded functions for most of the unsafe CRT functions. Buffer sizes for static arrays are calculated automatically.
无需任何进一步的代码更改,您就可以观察到大多数警告都是自动修复的。通过定义此窗口,将自动为大多数不安全 CRT 函数调用安全重载函数。静态数组的缓冲区大小是自动计算的。
Although Dynamically allocated buffers are not fixed by this way and we need to fix them manually. Please refer this linkfor further details.
虽然动态分配的缓冲区不是通过这种方式修复的,我们需要手动修复它们。请参阅此链接了解更多详情。
Below is a way to correct your example programatically
以下是一种以编程方式更正示例的方法
strcpy_s(extList->names[i], length, extName);
回答by djna
You do know how much to copy - you allocated space for it!
您确实知道要复制多少 - 您为其分配了空间!
Surely you wouldn't willingly copy more than the space you allocated?
你肯定不会愿意复制超过你分配的空间吗?
I would prefer to use a method that explicitly avoids buffer overruns by limiting the number of items copied. Back when I was a C programmer we used
我更愿意使用一种方法,通过限制复制的项目数量来明确避免缓冲区溢出。当我还是 C 程序员时,我们使用
dest = malloc(len); // note: where did we get len?
if ( dest is null ) panic! // note: malloc can fail
strncpy(dest, src, len);
dest[len-1] =0;
This is slightly messy, and has been pointed out is using strncpy() a method which really was originally designed for fixed-width fields rather than strings. However it does ach
这有点混乱,并且已经指出使用 strncpy() 的方法实际上最初是为固定宽度的字段而不是字符串设计的。然而它确实
There are methods such as strdup() and strlcpy() which may we help.
有诸如 strdup() 和 strlcpy() 之类的方法可以帮助我们。
My recommendations:
我的建议:
1). Your target should not be to suppress warnings but to make the code robust.
1)。您的目标不应该是抑制警告,而是要使代码健壮。
2). When copying strings you need to ensure these things:
2)。复制字符串时,您需要确保以下几点:
- Protect yourself from bad input, for example an unterminated or excessively long string.
- Protect yourself from malloc failures,
- Strongly prefer copies of counted numbers of characters to copying until we see a null
- If you claim to build a string, then make abolsutely sure you null terminate it
- 保护自己免受错误输入的影响,例如未终止或过长的字符串。
- 保护自己免受 malloc 失败的影响,
- 强烈喜欢计数字符的副本而不是复制,直到我们看到空值
- 如果您声称要构建一个字符串,那么请绝对确保您以 null 终止它
If strlcpy() is available in your environment then you could use it, otherwise why not write your own little utilityy function? Then if there are warnings in just that function you've localised then problem.
如果 strlcpy() 在您的环境中可用,那么您可以使用它,否则为什么不编写自己的小实用函数呢?然后,如果您已经本地化的那个函数中有警告,那么问题就来了。
回答by Mark B
In your first example, you know the length already. Since you aren't allocating length+1
bytes I'll assume that length
INCLUDES the null terminator. In that case, just std::copy
the string: std::copy(extName, extName + length, expList->names[i]);
在您的第一个示例中,您已经知道长度。由于您没有分配length+1
字节,因此我假设length
INCLUDES 空终止符。在这种情况下,只是std::copy
字符串:std::copy(extName, extName + length, expList->names[i]);
In your second example assuming the source strings are null terminated you could compute the destination string length and use std::copy
again to concatenate manually, or you could use std::string
and the std::copy
from the results of c_str
into your destination (Again assuming you allocated enough space for it).
在您的第二个示例中,假设源字符串为空终止,您可以计算目标字符串长度并std::copy
再次使用手动连接,或者您可以使用std::string
和std::copy
from 结果c_str
到您的目标(再次假设您为它分配了足够的空间)。
c_str()
does not allocate memory that would require external deletion.
c_str()
不分配需要外部删除的内存。
Finally note that sizeof(char)
will always be one and so is redundant in your malloc, although the number of bits in that character may not be 8 (See CHAR_BIT
).
最后请注意sizeof(char)
,尽管该字符中的位数可能不是 8(请参阅 参考资料CHAR_BIT
),但它始终为 1,因此在您的 malloc 中是多余的。
回答by oefe
If portability is not a concern, you can use 'strcpy_s'.
如果不考虑便携性,您可以使用'strcpy_s'。
回答by Simon
I think that you should replace all the function-calls if possibleto call an implementation of your own. A good example here would be a function to replace strcpy and call the compiler-specific version of strcpy inside it. Your implementation can then easily be modified to suit any compiler of your choice, specifically if you will be adding or changing platforms/compilers.
我认为如果可能的话,你应该替换所有的函数调用来调用你自己的实现。这里的一个很好的例子是一个函数来替换 strcpy 并在其中调用特定于编译器的 strcpy 版本。然后可以轻松修改您的实现以适合您选择的任何编译器,特别是如果您将添加或更改平台/编译器。
Example:
例子:
char* StringCopy(char* Destination, const char* Source, size_t DestinationSize)
{
#ifdef _MSC_VER
return strcpy_s(Destination, Source, DestinationSize);
#else
if(!(strlen(Source) >= DestinationSize))
return strcpy(Destination, Source);
else
return 0x0;
#endif
}
回答by Md Hasib Bin Shakur
If this code is only to be compiled for windows platform then it is better to use the secured version of these functions. However, if this code is going to compiled across multiple platforms(linux, Aix etc) then either you can disable the warning in your windows project configuration file (for example, .vcxproj) by using _CRT_SECURE_NO_WARNINGS or, you can use a code snippet like this one in places where those functions have been called in the .cpp file.
如果此代码只是为 windows 平台编译,那么最好使用这些函数的安全版本。但是,如果此代码要跨多个平台(linux、Aix 等)编译,那么您可以使用 _CRT_SECURE_NO_WARNINGS 禁用 Windows 项目配置文件(例如,.vcxproj)中的警告,或者,您可以使用类似的代码片段这是在 .cpp 文件中调用这些函数的地方。
#if _OS_ == _OS__WINDOWS
//secure function call
#else
//already written code
#endif
回答by cheng
as it is suggested in the message, use _CRT_SECURE_NO_WARNINGS to disable this warnings.
正如消息中建议的那样,使用 _CRT_SECURE_NO_WARNINGS 禁用此警告。
in ProjectProperties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions, add following macros:
在 ProjectProperties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions 中,添加以下宏:
_CRT_SECURE_NO_WARNINGS
_CRT_SECURE_NO_WARNINGS