В компиляторе 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.'
Как мне это предотвратить?
Похоже, что Microsoft устарела много вызовов, которые используют буферы для повышения безопасности кода. Однако предлагаемые ими решения не являются переносимыми. В любом случае, если вы не заинтересованы в использовании защищенной версии их вызовов (например, fopen_s ), вам необходимо поместить определение _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, как следует из предупреждения? Возвращает код ошибки, позволяющий проверить результат вызова функции.
Проблема с простым отключением предупреждений об устаревших функциях заключается в том, что Microsoft может удалить соответствующую функцию в более поздней версии CRT, нарушая ваш код (как указано ниже в комментариях, в этом случае это не произойдет с fopen, потому что это часть стандарты C & C ++ ISO).
In this context, "deprecated" just means that a function's use is not recommended; it does not indicate that the function is scheduled to be removed from the CRT.
- msdn ++++#pragma warning(disable:4996)
потому что предложенный _CRT_SECURE_NO_WARNINGS
и _CRT_SECURE_NO_DEPRECATE
оба не работали. В #define
s - видимому, работали в других контекстах, поэтому хедз-ап , что это , кажется, непоследовательно реализован. Подумайте об использовании библиотеки переносимости, такой как glib или переносимая среда выполнения Apache . Они обычно предоставляют безопасные, портативные альтернативы таким звонкам. Это тоже хорошо, потому что эти небезопасные вызовы устарели в большинстве современных сред.
fopen_s()
является стандартной функцией C fopen()
. Это просто Microsoft дерзкая. «Устаревший» подразумевает языковую функцию, которая может отсутствовать в будущих версиях стандартного языка / стандартных библиотек, как предписано комитетом по стандартам. Это не означает или не должно означать «мы, в одностороннем порядке, не думаем, что вы должны его использовать», независимо от того, насколько обоснован этот совет.
Если ваш код предназначен для другой ОС (например, 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
#if (defined(_MSC_VER) && (_MSC_VER >= 1600) ) ... #ELSE ...
того, чтобы охватить все дела, верно? Многие из безопасных функций Microsoft, включая fopen_s (), являются частью C11, поэтому теперь они должны быть переносимы. Вы должны понимать, что функции безопасности отличаются поведением исключений, а иногда и возвращаемыми значениями. Кроме того, вы должны знать, что хотя эти функции стандартизированы, это необязательная часть стандарта (Приложение K), которую, по крайней мере, glibc (по умолчанию в Linux) и libc FreeBSD не реализуют.
Тем не менее, я боролся с этой проблемой в течение нескольких лет. Я разместил здесь большой набор макросов преобразования . , Для вашей непосредственной проблемы, поместите следующий код во включаемый файл и включите его в ваш исходный код:
#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
Конечно, этот подход не реализует ожидаемое поведение исключения.
_s
- это не то же самое, что интерфейс C11 для проверки границ в целом. Некоторые имеют одинаковую синатуру, некоторые нет. Поскольку этот интерфейс является необязательным, его поддерживают лишь немногие реализации, потому что он по большей части не нужен. И ваш код - C ++, а не C, на который вы ссылаетесь в тексте. Для тех, кто использует версию Visual Studio 2017, похоже, что определение препроцессора, необходимое для выполнения небезопасных операций, изменилось. Используйте вместо этого:
#define _CRT_SECURE_NO_WARNINGS
Это будет компилироваться тогда.
freopen
. Я использую VisualStdio 2008. В этом случае я часто устанавливаю Preprocessor Definitions
Меню \ Проект \ [ProjectName] Свойства ... Alt + F7
Если щелкнуть это меню или нажать Alt + F7 в окне проекта, вы увидите окно «Страницы свойств» .
Затем посмотрите меню слева от окна.
Свойства конфигурации \ C / C ++ \ Препроцессор
Затем добавьте _CRT_SECURE_NO_WARNINGS
в \ Определения препроцессора .
#define
оставил много ошибок C4996. (@ankitsuthar ваш комментарий кажется мне неуместным. Этот ответ лаконичен, работает и отличается важными деталями от других.)
#ifdef _MSC_VER
.