предупреждение fopen устаревшее

В компиляторе 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.'

Как мне предотвратить это?

Ответов (10)

Решение

Похоже, что Microsoft отказалась от множества вызовов, использующих буферы для повышения безопасности кода. Однако предлагаемые ими решения непереносимы. В любом случае, если вы не заинтересованы в использовании защищенной версии их вызовов (например, fopen_s ), вам необходимо поместить определение _CRT_SECURE_NO_DEPRECATE перед вашими включенными файлами заголовков. Например:

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

Директиву препроцессора также можно добавить в настройки вашего проекта, чтобы применить ее ко всем файлам в проекте. Для этого добавьте _CRT_SECURE_NO_DEPRECATE в Свойства проекта -> Свойства конфигурации -> C/C++ -> Препроцессор -> Определения препроцессора .

Если ваш код предназначен для другой ОС (например, 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

Я использую VisualStdio 2008. В этом случае я часто устанавливаю Preprocessor Definitions

Меню \ Проект \ [Имя проекта] Свойства ... Alt + F7

Если щелкнуть это меню или нажать Alt + F7 в окне проекта, вы увидите окно «Страницы свойств» .

Затем посмотрите меню в левой части окна.

Свойства конфигурации \ C/C++ \ Preprocessor

Затем добавьте _CRT_SECURE_NO_WARNINGSв \ Preprocessor Definitions .

Для тех, кто использует версию Visual Studio 2017, кажется, что определение препроцессора, необходимое для выполнения небезопасных операций, изменилось. Вместо этого используйте:

#define _CRT_SECURE_NO_WARNINGS

Затем он будет компилироваться.

Ну, вы могли бы добавить:

#pragma warning (disable : 4996)

перед использованием fopen, но рассматривали ли вы возможность использования fopen_s, как следует из предупреждения? Он возвращает код ошибки, позволяющий проверить результат вызова функции.

Проблема с простым отключением предупреждений об устаревших функциях заключается в том, что Microsoft может удалить рассматриваемую функцию в более поздней версии CRT, нарушив ваш код (как указано ниже в комментариях, этого не произойдет в этом случае с fopen, потому что это часть стандарты ISO C и C++).

Рассмотрите возможность использования библиотеки переносимости, такой как glib или переносимая среда выполнения apache . Обычно они предоставляют безопасные портативные альтернативы подобным вызовам. Это тоже хорошо, потому что эти небезопасные вызовы устарели в большинстве современных сред.

Это просто нахальство Microsoft. «Устаревший» означает языковую функцию, которая может не быть предоставлена ​​в будущих версиях стандартного языка / стандартных библиотек, как это определено комитетом по стандартам. Это не означает и не должно означать: «мы в одностороннем порядке не думаем, что вы должны его использовать», независимо от того, насколько обоснован этот совет.

Многие из безопасных функций Microsoft, включая 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

Конечно, этот подход не реализует ожидаемого поведения исключения.