不推荐使用的警告

在使用 VisualStudio2005C + + 编译器时,当我的代码使用 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.'

我该如何防止这种情况发生?

189627 次浏览

看起来微软已经放弃了许多使用缓冲区来提高代码安全性的调用。然而,他们提供的解决方案是不可移植的。无论如何,如果您对使用他们的调用的安全版本(如 开门)不感兴趣,那么您需要在包含的头文件之前放置 _ CRT _ SECURE _ NO _ DEPRECATE的定义。例如:

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

还可以将预处理器指令添加到项目设置中,以对项目下的所有文件产生影响。为此,将 _ CRT _ SECURE _ NO _ DEPRECATE添加到 项目属性-> 配置属性-> C/C + +-> 预处理器-> 预处理器定义

你可以加上:

#pragma warning (disable : 4996)

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

禁用已废弃的函数警告的问题在于,微软可能会在 CRT 的后期版本中删除这个问题函数,从而破坏你的代码(正如下面的评论中所说的,这种情况在 fopen 的实例中不会发生,因为它是 C & C + + ISO 标准的一部分)。

考虑使用可移植性库,如 油嘴滑舌Apache可移植运行时。这些调用通常提供安全的、可移植的替代方案。这也是一件好事,因为这些不安全的调用在大多数现代环境中都是不推荐的。

这只是微软的厚颜无耻。“弃用”意味着一种语言特性,这种特性可能不会在标准语言/标准库的未来版本中提供,这是标准委员会规定的。这并不意味着,或者说不应该意味着,“我们单方面认为你们不应该使用它”,无论这一建议有多么充分的理由。

如果你的代码是为不同的操作系统(比如 Mac OS X,Linux)编写的,你可以使用以下代码:

#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE
#endif

当我试图添加 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

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

我通过以下方法解决了这个问题:

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

如果您希望在许多平台上使用它,您可以像注释中那样使用如下定义:

#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

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

然而,我与这个问题斗争了几年。我张贴了一个更大的转换宏集 给你。,对于您的直接问题,把以下代码包含在一个包含文件,并包括在您的源代码:

#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

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

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

#define _CRT_SECURE_NO_WARNINGS

到时候就能编译了。

我正在使用 VisualStudio 2008。 在这种情况下,我经常设置 < strong > Preprocessor Definitions

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

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

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

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

然后将 _CRT_SECURE_NO_WARNINGS添加到 预处理器定义