2008-08-18 29 views
52

En compilador Visual Studio 2005 C++, recibo la siguiente advertencia cuando mi código usa fopen y llamadas similares.advertencia obsoleto 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.' 

¿Cómo puedo evitar esto?

Respuesta

97

Parece que Microsoft ha desaprobado muchas llamadas que usan almacenamientos intermedios para mejorar la seguridad del código. Sin embargo, las soluciones que brindan no son portátiles. De todos modos, si no está interesado en utilizar la versión segura de sus llamadas (como fopen_s), debe colocar una definición de _CRT_SECURE_NO_DEPRECATE antes de los archivos de encabezado incluidos. Por ejemplo:

#define _CRT_SECURE_NO_DEPRECATE 
#include <stdio.h> 

La directiva de preprocesador también se puede añadir a la configuración del proyecto para efectuar en todos los archivos del proyecto. Para hacer esto, agregue _CRT_SECURE_NO_DEPRECATE a Propiedades del proyecto -> Propiedades de configuración -> C/C++ -> Preprocesador -> Definiciones de preprocesador.

+8

probablemente debería hacer algo como esto, sin embargo: #ifdef _WIN32 #define _CRT_SECURE_NO_DEPRECATE #endif # include Debido a que otras plataformas no necesitan que se define durante el tiempo de compilación. – markwatson

+2

Sí que efectivamente funcionó. –

+1

@markwatson Una mejor guardia sería verificar '#ifdef _MSC_VER'. – MicroVirus

23

Bien se podría añadir un:

#pragma warning (disable : 4996) 

antes de utilizar fopen, pero ha considerado el uso de fopen_s como sugiere la advertencia? Devuelve un código de error que le permite verificar el resultado de la llamada a la función.

El problema con la desactivación de advertencias de funciones obsoletas es que Microsoft puede eliminar la función en cuestión en una versión posterior del CRT, rompiendo su código (como se indica a continuación en los comentarios, esto no ocurrirá en este caso con fopen porque es parte de los estándares C & C++ ISO).

+31

"Microsoft puede eliminar la función en cuestión en una versión posterior de la CRT", si ya no desean implementar los estándares C o C++. –

+3

Algunas personas también se dirigen a plataformas que no son MS. Y con muchas de estas funciones, no hay realmente una ganancia de seguridad notable. – sstn

+8

Para futuros usuarios de Google: 'En este contexto, 'obsoleto' solo significa que no se recomienda el uso de una función; no indica que la función esté programada para ser eliminada del CRT. - [msdn] (http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx) ++++ – Navin

4

Considere utilizar una biblioteca de portabilidad como glib o apache portable runtime. Por lo general, ofrecen alternativas seguras y portátiles para llamadas como estas. También es una buena idea, porque estas llamadas inseguras están en desuso en la mayoría de los entornos modernos.

11

Esto es solo Microsoft siendo descarado. "Obsoleto" implica una función de idioma que puede no proporcionarse en futuras versiones del lenguaje estándar/bibliotecas estándar, según lo decida el comité de estándares. No significa, o no debería significar, "nosotros, unilateralmente, no creemos que deba usarlo", no importa cuán bien fundado sea ese consejo.

+14

El significado de la palabra inglesa "deprecate" es precisamente la segunda cosa: "creemos que no deberías usarlo". Pero en términos de informática, recientemente ha llegado a tener un significado mucho más débil, "podría no ser aconsejable usarlo, porque estamos pensando en eliminarlo, y hemos proporcionado algo que creemos que es mejor". –

7

Si el código está destinado a un sistema operativo diferente (como Mac OS     X, Linux), es posible utilizar las siguientes:

#ifdef _WIN32 
#define _CRT_SECURE_NO_DEPRECATE 
#endif 
0

También tiene el mismo problema. Cuando trato de agregar la biblioteca opencv

#include <opencv\cv.h> 

No recibí una advertencia, pero un error.

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 

También utilicé las directivas de preprocesador mencionadas. Pero eso no resolvió el problema.

Lo resuelto por hacer de la siguiente manera:

  • Ir a Propiedades -> C/C++ -> encabezados precompilados -> Seleccione No utilizar encabezados precompilados en el encabezado precompilado. uso
1

Si quieres que sea utilizado en muchas plataformas, se podía como se ha comentado define como:

#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 
+0

Su complejo #IF solo se dirige a las plataformas, no a las versiones del compilador. ¿Qué tal '' if (definido (_MSC_VER) && (_MSC_VER> = 1600)) ... #ELSE ... 'Eso debería cubrir todos los casos, ¿verdad? – riderBill

+0

_MSC_VER = 1600 puede no ser la primera versión que desaprobó fopen(), etc. Fue la primera versión en la que encontré el problema. – riderBill

+0

Parece que la primera versión de MSVC con (algunas de) las funciones seguras fue 2005, _MSC_VER = 1400. – riderBill

1

Muchas de las funciones de seguridad de Microsoft, incluyendo fopen_s(), forman parte de C11, por lo deberían ser portátiles ahora. Debe tener en cuenta que las funciones de seguridad difieren en comportamientos de excepción y, en ocasiones, en valores de retorno. Además, debe tener en cuenta que, si bien estas funciones están estandarizadas, es una opcional parte del estándar (Anexo K) que al menos glibc (predeterminado en Linux) y la libc de FreeBSD no implementan.

Sin embargo, luché contra este problema durante unos años. He publicado un conjunto mayor de macros de conversión here., para su problema de inmediato, poner el siguiente código en un archivo de inclusión, e incluirlo en su código fuente:

#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 

Por supuesto, este enfoque no implementa el comportamiento excepción esperada .

+0

MS '_s' no son lo mismo que la interfaz de comprobación de límites C11 en general. Algunos tienen la misma sinceridad, otros no. Como esa interfaz es opcional, pocas implementaciones la soportan, por lo general es innecesaria. Y su código es C++, no C a lo que se refiere en el texto. – Olaf

+0

@Olaf: Hmm. No puedo abordar la comprobación de límites, salvo señalar mi advertencia de comportamiento de excepción. – riderBill

+0

Tiene razón en que cité el estándar C11 (a diferencia de C++ 14 o 17). Las funciones están disponibles en versiones recientes de los compiladores C++ de Microsoft. Resulta que el Anexo K no es ampliamente compatible fuera de MSVS. Jonathan Leffler comentó [aquí] (https://stackoverflow.com/questions/858252/alternatives-to-ms-strncpy-s/35193374#35193374) que las versiones MS no coinciden con las especificaciones del Anexo K. Demasiado para la portabilidad. – riderBill

1

Para aquellos que están usando la versión Visual Studio 2017, parece que la definición del preprocesador requerida para ejecutar operaciones inseguras ha cambiado. Use en su lugar:

#define _CRT_SECURE_NO_WARNINGS 

Se compilará a continuación.

3

I'am usando VisualStdio 2008. En este caso, a menudo establece Preprocessor Definitions

Menú \ proyecto \ [Nombre del Proyecto] Propiedades ... Alt + F7

Si haga clic en este menú o presione Alt + F7 en la ventana del proyecto, puede ver "Páginas de propiedades" ventana.

Luego, vea el menú a la izquierda de la ventana.

Propiedades de configuración \ C/C++ \ preprocesador

A continuación, añadir _CRT_SECURE_NO_WARNINGS a \ definiciones del preprocesador.

+0

Vea primero este [cómo-responder ] (https://stackoverflow.com/help/how-to-answer) Esta pregunta es respondida antes, obviamente, puede agregar su respuesta aquí. Pero necesita comprender algunos puntos antes de responder. Primero, no haga agregue una respuesta que se agregó previamente con el mismo código o sugerencia. Segundo, no agregue una respuesta demasiado complicada si el usuario ha preguntado muy específicamente sobre el problema y lo que necesita para resolverlo. Tercero, puede agregar un comentario si quieres sugerir cualquier cosa ng la respuesta o pregunta. –