70

On Visual Studio 2005 C++ compiler, I get the following warning when my code uses the fopen and such calls.

1>foo.cpp(5) : warning C4996: 'fopen' was declared deprecated
1>        c:\program files\microsoft visual studio 8\vc\include\stdio.h(234) : see declaration of 'fopen'
1>        Message: 'This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'

How do I prevent this?

Leos313
  • 3,729
  • 4
  • 29
  • 61
Ashwin Nanjappa
  • 68,458
  • 72
  • 198
  • 283

10 Answers10

131

It looks like Microsoft has deprecated lots of calls which use buffers to improve code security. However, the solutions they're providing aren't portable. Anyway, if you aren't interested in using the secure version of their calls (like fopen_s), you need to place a definition of _CRT_SECURE_NO_DEPRECATE before your included header files. For example:

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

The preprocessor directive can also be added to your project settings to effect it on all the files under the project. To do this add _CRT_SECURE_NO_DEPRECATE to Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions.

Ashwin Nanjappa
  • 68,458
  • 72
  • 198
  • 283
  • 10
    You should probably do something like this though: #ifdef _WIN32 #define _CRT_SECURE_NO_DEPRECATE #endif #include Because other platforms don't need that defined during compile time. – markwatson Aug 13 '10 at 19:08
  • 1
    @markwatson A better guard would be to check `#ifdef _MSC_VER`. – MicroVirus Jun 03 '16 at 01:47
30

Well you could add a:

#pragma warning (disable : 4996)

before you use fopen, but have you considered using fopen_s as the warning suggests? It returns an error code allowing you to check the result of the function call.

The problem with just disabling deprecated function warnings is that Microsoft may remove the function in question in a later version of the CRT, breaking your code (as stated below in the comments, this won't happen in this instance with fopen because it's part of the C & C++ ISO standards).

John Sibly
  • 21,309
  • 7
  • 55
  • 78
  • 39
    "Microsoft may remove the function in question in a later version of the CRT" - if they no longer wish to implement the C or C++ standards. – Steve Jessop May 25 '09 at 13:15
  • 5
    Some people target non-MS platforms as well. And with a lot of these _s functions, there is not really a well-notable security gain. – sstn Aug 11 '11 at 07:49
  • 15
    For future googlers: `In this context, "deprecated" just means that a function's use is not recommended; it does not indicate that the function is scheduled to be removed from the CRT.` -[msdn](http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx) ++++ – Navin Mar 19 '13 at 20:38
  • 1
    @SteveJessop They already knowingly and willingly break the standard. See [this](http://msdn.microsoft.com/en-us/library/x84h5b78.aspx). – ApproachingDarknessFish Feb 19 '14 at 06:54
  • 5
    In VS2013 I needed to use `#pragma warning(disable:4996)` because the suggested `_CRT_SECURE_NO_WARNINGS` and `_CRT_SECURE_NO_DEPRECATE` both did not work. The `#define`s seem to work in other contexts, so a heads-up that this appears to be inconsistently implemented. – Bill Weinman May 13 '14 at 04:01
  • I could've used **fopen_s**, but since this came up with some code which I wanted to be as portable as possible, I don't prefer that solution. I find it difficult to believe that Microsoft will completely remove the standard library calls. They might make them pretty hard to use, but they will need to keep them around for old code. – Ashwin Nanjappa Aug 18 '08 at 13:13
13

This is just Microsoft being cheeky. "Deprecated" implies a language feature that may not be provided in future versions of the standard language / standard libraries, as decreed by the standards committee. It does not, or should not mean, "we, unilaterally, don't think you should use it", no matter how well-founded that advice is.

tragomaskhalos
  • 2,563
  • 2
  • 16
  • 10
  • 14
    The meaning of the English word "deprecate" is precisely the second thing: "we think you shouldn't use it". But in computer parlance it has recently come to have a much weaker meaning, "it might not be wise to use it, because we're kind of thinking of removing it, and we've provided something we think is better". – Steve Jessop May 25 '09 at 13:22
9

If you code is intended for a different OS (like Mac OS X, Linux) you may use following:

#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE
#endif
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Magnetron
  • 293
  • 4
  • 9
5

I'am using VisualStdio 2008. In this case I often set Preprocessor Definitions

Menu \ Project \ [ProjectName] Properties... Alt+F7

If click this menu or press Alt + F7 in project window, you can see "Property Pages" window.

Then see menu on left of window.

Configuration Properties \ C/C++ \ Preprocessor

Then add _CRT_SECURE_NO_WARNINGS to \ Preprocessor Definitions.

Bryant
  • 304
  • 2
  • 15
  • Please see this first [how-to-answer](https://stackoverflow.com/help/how-to-answer) This question is answered before, obviously, you can add your answer here. But You Need to understand some points before answering. First, don't add an answer which is previously added with the same code or suggestion. Second, don't add an overly complicated answer if the user has asked very specifically about the problem and what he needs to solve this. Third, You can add a comment if you want to suggest anything regarding the answer or question. – ankit suthar Jul 15 '17 at 04:48
  • This is the only answer that worked for me in Visual Studio 2017. `#define` left lots of C4996 errors. (@ankitsuthar your comment seems misplaced to me. This answer is concise, it works, and differs in important details from the others.) – Bob Stein Feb 06 '19 at 21:02
4

Consider using a portability library like glib or the apache portable runtime. These usually provide safe, portable alternatives to calls like these. It's a good thing too, because these insecure calls are deprecated in most modern environments.

Joseph Holsten
  • 19,514
  • 6
  • 23
  • 28
  • 1
    The **portable** alternative to Microsoft's one-off, not-quite-standards-compliant, non-portable implementation of the optional Annex K function `fopen_s()` is the C standard function `fopen()`. – Andrew Henle Feb 04 '20 at 12:26
1

If you want it to be used on many platforms, you could as commented use defines like:

#if defined(_MSC_VER) || defined(WIN32)  || defined(_WIN32) || defined(__WIN32__) \
                        || defined(WIN64)    || defined(_WIN64) || defined(__WIN64__) 

        errno_t err = fopen_s(&stream,name, "w");

#endif

#if defined(unix)        || defined(__unix)      || defined(__unix__) \
                        || defined(linux)       || defined(__linux)     || defined(__linux__) \
                        || defined(sun)         || defined(__sun) \
                        || defined(BSD)         || defined(__OpenBSD__) || defined(__NetBSD__) \
                        || defined(__FreeBSD__) || defined __DragonFly__ \
                        || defined(sgi)         || defined(__sgi) \
                        || defined(__MACOSX__)  || defined(__APPLE__) \
                        || defined(__CYGWIN__) 

        stream = fopen(name, "w");

#endif
JTIM
  • 2,555
  • 28
  • 65
  • Your complex #IF only addresses platforms, not compiler versions. How about `#if (defined(_MSC_VER) && (_MSC_VER >= 1600) ) ... #ELSE ...` That should cover all cases, right? – riderBill Feb 04 '16 at 02:46
  • _MSC_VER = 1600 may not be the first version that deprecated fopen(), etc. It was the first version in which I encountered the issue. – riderBill Feb 04 '16 at 02:49
  • Looks like the first version of MSVC with (some of) the secure functions was 2005, _MSC_VER = 1400. – riderBill Feb 06 '16 at 23:56
1

Many of Microsoft's secure functions, including fopen_s(), are part of C11, so they should be portable now. You should realize that the secure functions differ in exception behaviors and sometimes in return values. Additionally you need to be aware that while these functions are standardized, it's an optional part of the standard (Annex K) that at least glibc (default on Linux) and FreeBSD's libc don't implement.

However, I fought this problem for a few years. I posted a larger set of conversion macros here., For your immediate problem, put the following code in an include file, and include it in your source code:

#pragma once
#if !defined(FCN_S_MACROS_H)
   #define   FCN_S_MACROS_H

   #include <cstdio>
   #include <string> // Need this for _stricmp
   using namespace std;

   // _MSC_VER = 1400 is MSVC 2005. _MSC_VER = 1600 (MSVC 2010) was the current
   // value when I wrote (some of) these macros.

   #if (defined(_MSC_VER) && (_MSC_VER >= 1400) )

      inline extern
      FILE*   fcnSMacro_fopen_s(char *fname, char *mode)
      {  FILE *fptr;
         fopen_s(&fptr, fname, mode);
         return fptr;
      }
      #define fopen(fname, mode)            fcnSMacro_fopen_s((fname), (mode))

   #else
      #define fopen_s(fp, fmt, mode)        *(fp)=fopen( (fmt), (mode))

   #endif //_MSC_VER

#endif // FCN_S_MACROS_H

Of course this approach does not implement the expected exception behavior.

Giel
  • 2,565
  • 2
  • 18
  • 22
riderBill
  • 720
  • 6
  • 15
  • 1
    MS `_s` are not the same as C11 bounds checking interface in general. Some have the same sinature, some don't. As that interface is optional, few implementations support it, bercause it is mostly unnecessary. And your code is C++, not C which you refer to in the text. – too honest for this site Sep 17 '17 at 16:30
  • @Olaf: Hmm. I can't address the bounds checking, other than to point out my exception behavior caveat. – riderBill Sep 19 '17 at 01:13
  • You are right that I cited the C11 standard (as opposed to C++14 or 17). The functions are available in recent versions of Microsoft's C++ compilers. It turns out that Annex K is not widely supported outside of MSVS. Jonathan Leffler commented [here](https://stackoverflow.com/questions/858252/alternatives-to-ms-strncpy-s/35193374#35193374) that the MS versions don't actually match the Annex K specifications. So much for portability. – riderBill Sep 19 '17 at 01:14
  • 1
    I'd appreciate if you read my comments _completely_. MSVC does not really use the BCI, but their own soup. MSVC has not ben compliant since at least 18 years now and were very clear about not intending to, at least including C99 mandatory featues like VLAs which are supported by every modern compiler since years already (including major embedded). – too honest for this site Sep 19 '17 at 01:26
  • The questioner tagged Visual C++. I copied the code from a larger C++ file. For C, I guess the includes would be *stdio.h* and *string.h* (strings aren't used in the code above, though). I don't need the *using namespace std;* statement -- is that valid in C? I'm thinking the *inline extern* ... should be *static inline* in C, to avoid linker problems. I don't write much C code these days. Add a comment if I'm wrong. – riderBill Sep 19 '17 at 01:26
  • @Olaf. No need to be rude. I don't know anything about the bounds checking interface you are referring to. That's what I meant by "I can't address ..." My original comment continued with "although tbh, that's not what I meant at the time." That last part disappeared while I was editing (I hit return -- stupid idea for return to mean send or save, IMHO). I didn't feel it was important anyway. Feel free to provide an answer explaining the bounds checking interface. If it's important, I'd like to know about it. – riderBill Sep 21 '17 at 22:28
  • No one was being rude. I find such intros quite insulting. "Many of Microsoft's secure functions, including fopen_s(), are part of C11, so they should be portable now" and "You are right that I cited the C11 standard" - so we are safe to expect you know the standard, why else would you state this? About the rest: google. All posts can be edited, comments for 5 minutes. That should be sufficient. Maybe you should not have skipped the [tour]? For future references: http://port70.net/~nsz/c/c11/n1570.html I keep this under my pillow (See appendix K for this discussion) – too honest for this site Sep 21 '17 at 22:36
  • That last macro definition needs parens round the assignment, to protect it against higher-precedence operators in the expansion context. You also need to return `errno` on failure; try `#define fopen_s(f, name, mode) ((*(f) = fopen(name, mode)) : 0 ? errno)` instead. – Toby Speight Aug 12 '19 at 08:04
1

For those who are using Visual Studio 2017 version, it seems like the preprocessor definition required to run unsafe operations has changed. Use instead:

#define _CRT_SECURE_NO_WARNINGS

It will compile then.

  • 1
    This does not appear to work for me. Still get compile errors for `freopen`. – Levi Roberts Oct 27 '18 at 16:38
  • 1
    @LeviRoberts you have to put this define at the very top of the file, the error is generated when some header files are included – jrh Nov 03 '20 at 20:27
0

I also got the same problem. When I try to add the opencv library

#include <opencv\cv.h>

I got not a warning but an error.

error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    c:\program files (x86)\opencv\build\include\opencv2\flann\logger.h  

I also used the preprocessor directives as mentioned. But that didn't solve the problem.

I solved it by doing as follows:

  • Go to Properties -> C/C++ -> Precompiled Headers -> Choose Not Using Precompiled Headers in Precompiled Header.
Karthik_elan
  • 193
  • 1
  • 4
  • 12