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

В компиляторе Visual Studio 2005 С++ я получаю следующее предупреждение, когда в моем коде используется 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.'

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

Ответ 1

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

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>

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

Ответ 2

Ну, вы можете добавить:

#pragma warning (disable : 4996)

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

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

Ответ 3

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

Ответ 4

@John Sibly: Спасибо за информативный комментарий. Я мог бы использовать fopen_s, но так как это придумало какой-то код, который я хотел бы быть как можно более переносимым, я не предпочитаю этого решения. Мне трудно поверить, что Microsoft полностью удалит стандартные вызовы библиотеки. Они могут сделать их довольно сложными в использовании, но им нужно будет хранить их для старого кода.

Ответ 5

Если код предназначен для другой ОС (например, Mac OS X X, Linux), вы можете использовать следующее:

#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE
#endif

Ответ 6

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

Ответ 7

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

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

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

Затем см. меню слева от окна.

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

Затем добавьте _CRT_SECURE_NO_WARNINGS в \Определения препроцессора.

Ответ 8

Если вы хотите, чтобы он использовался на многих платформах, вы могли бы использовать, как указано в комментариях:

#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

Ответ 9

Многие из защищенных функций Microsoft, включая fopen_s(), являются частью C11, поэтому теперь они должны быть переносимыми. Вы должны понимать, что защищенные функции различаются по типу исключений, а иногда и по возвратным значениям. Кроме того, вам нужно знать, что, хотя эти функции стандартизированы, это необязательная часть стандарта (приложение K), по крайней мере, glibc (по умолчанию в Linux) и libBS libbs не реализуются.

Однако я боролся с этой проблемой в течение нескольких лет. Я разместил более крупный набор макросов преобразования здесь.. Для вашей непосредственной проблемы поставьте следующий код в include файл и включите его в исходный код:

#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

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

Ответ 10

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

#define _CRT_SECURE_NO_WARNINGS

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

Ответ 11

У меня тоже такая же проблема. Когда я пытаюсь добавить библиотеку 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/С++ → Предварительно скомпилированные заголовки → Выберите Не использовать предварительно скомпилированные заголовки в предварительно скомпилированном заголовке.