C++ 'strcpy' gives a Warning (C4996)

2019-01-14 12:44发布

问题:

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.

回答1:

This function (strcpy) is considered unsafe due to the fact that there is no bounds checking and can lead to buffer overflow. (Actually strcpy is infamous for overflow exploits and all programmers avoid it-or at least should avoid it). 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!). There is no problem with your code, i.e. 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



回答2:

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

Microsoft, in an effort to promote safer coding in C and C++ has provided a suite of replacement functions for the dangerous string methods. Typically they have the original name postpended with _s. Hence the Microsoft secure version of strcpy is strcpy_s as recommended in the warning. Note this a Microsoft specific feature, it's not ubiquitious.

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

Do not use functions such as strcpy or strcpy_s or strncpy. Use the copy constructor or assignment operator of the string class. Or if you really need to copy buffers, use std::copy.



回答4:

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.

You have two options:

  • if you're unsure - do what VC++ says and use "safe" functions. 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.


回答5:

There is actualy a way to avoid this warning, still use strcpy, and be safe:

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



回答6:

That warning is basically informing you that strcpy is deprecated, because copying a string until \0 can easily lead to nasty problems (buffer overruns). 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).

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.

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



回答7:

#pragma warning(disable: 4996)

use above code in the first line of your code.



回答8:

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:

#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


回答9:

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.

ignore method 1: project globle scope: add _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:

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