关于Visual c ++:fopen不建议使用的警告

关于Visual c ++:fopen不建议使用的警告

fopen deprecated warning

在Visual Studio 2005 C ++编译器上,当我的代码使用fopen和此类调用时,出现以下警告。

1
2
3
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.'

我该如何预防?


看起来Microsoft已经弃用了许多使用缓冲区来提高代码安全性的调用。但是,他们提供的解决方案不是便携式的。无论如何,如果您对使用其调用的安全版本(例如fopen_s)不感兴趣,则需要在包含的头文件之前放置_CRT_SECURE_NO_DEPRECATE的定义。例如:

1
2
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

也可以将预处理器指令添加到您的项目设置中,以对项目下的所有文件生效。为此,将_CRT_SECURE_NO_DEPRECATE添加到项目属性->配置属性-> C / C ++->预处理程序->预处理程序定义。


好吧,您可以添加:

1
#pragma warning (disable : 4996)

在使用fopen之前,但是您是否考虑过按照警告提示使用fopen_s?它返回一个错误代码,允许您检查函数调用的结果。

仅禁用不推荐使用的功能警告的问题在于,Microsoft可能会在更高版本的CRT中删除有问题的功能,从而破坏您的代码(如注释中所述,在这种情况下,使用fopen不会发生这种情况,因为它是C&C ++ ISO标准)。


这只是微软的厚脸皮。"不推荐使用"表示标准委员会/组织在将来的标准语言/标准库版本中可能未提供的语言功能。无论该建议有多充分的依据,它都不会或不应该表示"我们单方面认为您不应该使用它"。


如果您的代码是针对其他操作系统(例如MacOSX,Linux)的,则可以使用以下代码:

1
2
3
#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE
#endif

我正在使用VisualStdio 2008。
在这种情况下,我经常设置Preprocessor Definitions

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

如果单击此菜单或在项目窗口中按Alt + F7,则可以看到"属性页"窗口。

然后查看窗口左侧的菜单。

Configuration Properties \ C/C++ \ Preprocessor

然后将_CRT_SECURE_NO_WARNINGS添加到预处理程序定义。


考虑使用可移植性库,例如glib或apache可移植运行时。这些通常可以为此类呼叫提供安全,便携式的替代方法。这也是一件好事,因为这些不安全的调用在大多数现代环境中已被弃用。


对于使用Visual Studio 2017版本的用户,似乎运行不安全操作所需的预处理器定义已更改。改用:

1
#define _CRT_SECURE_NO_WARNINGS

然后它将编译。


Microsoft的许多安全功能,包括fopen_s(),都是C11的一部分,因此它们现在应该是可移植的。您应该认识到安全功能在异常行为和返回值方面有所不同。另外,您还需要注意,尽管这些功能已经标准化,但它是标准(附件K)的可选部分,至少glibc(Linux上的默认设置)和FreeBSD的libc并未实现。

但是,我为此问题奋斗了几年。我在此处发布了一组较大的转换宏。,对于您的直接问题,请将以下代码放在包含文件中,并将其包含在源代码中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#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

当然,这种方法不会实现预期的异常行为。


如果要在许多平台上使用它,则可以使用注释定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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

我也遇到同样的问题。当我尝试添加opencv库时

1
#include <opencv\cv.h>

我不是警告,而是错误。

1
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

我还使用了提到的预处理器指令。但这并不能解决问题。

我通过以下方法解决了它:

  • 转到"属性"->" C / C ++"->"预编译头"->"在预编译头中选择不使用预编译头"。


推荐阅读