70

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

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

我该如何防止这种情况?

4

10 回答 10

134

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

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

预处理器指令也可以添加到您的项目设置中,以影响项目下的所有文件。为此,将_CRT_SECURE_NO_DEPRECATE添加到Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions

于 2008-08-18T09:39:16.510 回答
31

那么你可以添加一个:

#pragma warning (disable : 4996)

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

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

于 2008-08-18T12:18:13.647 回答
13

这只是微软厚脸皮。根据标准委员会的规定,“已弃用”表示标准语言/标准库的未来版本中可能不会提供的语言功能。它并不或不应该意味着“我们单方面认为您不应该使用它”,无论该建议多么有根据。

于 2008-11-12T17:34:49.640 回答
10

如果您的代码适用于不同的操作系统(如 Mac OS X、Linux),您可以使用以下内容:

#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE
#endif
于 2011-11-09T18:02:20.830 回答
5

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

菜单 \ 项目 \ [项目名称] 属性... Alt+F7

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

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

配置属性\C/C++\预处理器

然后添加_CRT_SECURE_NO_WARNINGS\Preprocessor Definitions

于 2017-07-15T03:35:23.293 回答
4

考虑使用像glibapache 可移植运行时这样的可移植库。这些通常为此类调用提供安全、便携的替代方案。这也是一件好事,因为这些不安全的调用在大多数现代环境中已被弃用。

于 2008-09-18T11:15:58.880 回答
1

如果您希望它在许多平台上使用,您可以按照评论使用定义如下:

#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
于 2015-02-24T09:57:23.680 回答
1

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

然而,我与这个问题斗争了几年。我在这里发布了一组更大的转换宏, 对于您的直接问题,请将以下代码放入包含文件中,并将其包含在您的源代码中:

#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

当然,这种方法并没有实现预期的异常行为。

于 2016-02-04T02:38:26.177 回答
1

对于那些使用 Visual Studio 2017 版本的人来说,运行不安全操作所需的预处理器定义似乎发生了变化。改用:

#define _CRT_SECURE_NO_WARNINGS

然后它会编译。

于 2017-03-20T16:03:40.323 回答
0

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

#include <opencv\cv.h>

我得到的不是警告而是错误。

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  

我还使用了前面提到的预处理器指令。但这并没有解决问题。

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

  • 转到 Properties -> C/C++ -> Precompiled Headers -> 选择 Not Using Precompiled Headers in Precompiled Header。
于 2014-12-30T17:10:55.423 回答