c++ windows visual-studio debugging

c++ - Cómo deshacerse de las advertencias/errores "inseguros" en Visual Studio(strcpy, sprintf, strdup)



windows visual-studio (9)

Estoy tratando de deshacerme de algunas advertencias del compilador que dicen que strcpy, sprintf, etc. no son seguras. Entiendo por qué son inseguros, pero no puedo pensar en una buena manera de arreglar el código, en un estilo C ++.

Aquí un extracto del código:

extList->names[i]=(char *)malloc(length*sizeof(char)); strcpy(extList->names[i],extName); // unsafe // strncpy(extList->names[i],extName,length); // also unsafe

Aquí está el mensaje:

C4996: ''strcpy'': esta función o variable puede no ser segura. Considera usar strcpy_s en su lugar. Para deshabilitar la desaprobación, utilice _CRT_SECURE_NO_WARNINGS. Consulte la ayuda en línea para obtener detalles.

No puedo pensar en una forma segura de copiar los datos en C ++ sin saber la longitud de las cosas para copiar. Sé que hay strlen (), pero eso también es inseguro ya que asume (quizás incorrectamente) que los datos están terminados en nulo.

También:

// used to concatenate: sprintf(extStr,"%s%s",platExtStr,glExtStr);

C4996: ''sprintf'': esta función o variable puede no ser segura. Considere el uso de sprintf_s en su lugar. Para deshabilitar la desaprobación, utilice _CRT_SECURE_NO_WARNINGS. Consulte la ayuda en línea para obtener detalles.

Usar std :: string para concatenar es bastante fácil, pero luego necesito obtener los datos en extStr de alguna manera (y no usar strcpy, lol). La función string :: c_str () devuelve un puntero a datos no modificables, por lo que no puedo establecer extStr igual a él. (Y ni siquiera estoy seguro de si el puntero c_str () necesita ser borrado más tarde. ¿Asigna espacio usando "nuevo"?)

¿Algún consejo sobre esto? Esto es parte de un archivo de 10,000 líneas que no es mío ... así que no estoy exactamente interesado en volver a escribir la cosa en la forma C ++.


Aquí hay otra respuesta a esta pregunta.

#ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4996) #endif strcpy(destination, source); #ifdef _MSC_VER #pragma warning(pop) #endif


Creo que deberías reemplazar todas las llamadas de función, si es posible, para llamar a una implementación propia. Un buen ejemplo aquí sería una función para reemplazar strcpy y llamar dentro de la versión específica de compilador de strcpy. Su implementación se puede modificar fácilmente para adaptarse a cualquier compilador de su elección, específicamente si va a agregar o cambiar plataformas / compiladores.

Ejemplo:

char* StringCopy(char* Destination, const char* Source, size_t DestinationSize) { #ifdef _MSC_VER return strcpy_s(Destination, Source, DestinationSize); #else if(!(strlen(Source) >= DestinationSize)) return strcpy(Destination, Source); else return 0x0; #endif }


En tu primer ejemplo, ya sabes la longitud. Como no está asignando length+1 bytes, asumiré que la length INCLUYE el terminador nulo. En ese caso, solo std::copy la cadena: std::copy(extName, extName + length, expList->names[i]);

En su segundo ejemplo, asumiendo que las cadenas de origen están terminadas en nulo, puede calcular la longitud de la cadena de destino y usar std::copy nuevamente para concatenar manualmente, o puede usar std::string y el std::copy desde los resultados de c_str hasta su Destino (una vez más, suponiendo que ha asignado suficiente espacio para ello).

c_str() no asigna memoria que requeriría una eliminación externa.

Finalmente, tenga en cuenta que sizeof(char) siempre será uno y, por lo tanto, es redundante en su malloc, aunque la cantidad de bits en ese carácter no sea 8 (consulte CHAR_BIT ).


Realmente no necesitas pragmas para deshabilitarlos.

Para win32 / msvc, en ProjectProperties -> Propiedades de configuración -> C / C ++ -> Preprocesador -> Definiciones de preprocesador, agregue las siguientes macros:

_CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_DEPRECATE

O puede pasarlos en los parámetros de la línea de comandos (-D_CRT_SECURE_NO_DEPRECATE). Probablemente pueda # definirlos al comienzo de ciertos archivos * .cpp. Además, probablemente haya más de ellos (ver crtdefs.h - parece que hay muchos de ellos ...). Este tipo de advertencias normalmente le indican con qué macros puede deshabilitarlas, simplemente lea la salida del compilador.


Si este código solo se compila para la plataforma de Windows, es mejor utilizar la versión segura de estas funciones. Sin embargo, si este código se va a compilar en múltiples plataformas (Linux, Aix, etc.), puede desactivar la advertencia en el archivo de configuración de su proyecto de Windows (por ejemplo, .vcxproj) usando _CRT_SECURE_NO_WARNINGS o puede usar un fragmento de código como este en lugares donde esas funciones han sido llamadas en el archivo .cpp.

#if _OS_ == _OS__WINDOWS //secure function call #else //already written code #endif


Si la portabilidad no es una preocupación, puede usar ''strcpy_s'' .


Si su objetivo es simplemente deshacerse de las advertencias ... simplemente defina esto _CRT_SECURE_NO_WARNINGS y suprimirá todas las advertencias de desaprobación. Pero esto no solucionará los problemas subyacentes con funciones CRT inseguras.

Si está en la versión de Visual Studio> = 2005 y desea corregir estas advertencias de manera adecuada ... el método más sencillo es #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 y #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1 en su proyecto.

sin más cambios de código, puede observar que la mayoría de las advertencias se corrigen automáticamente. Al definir esta ventana, se activarán automáticamente las funciones sobrecargadas seguras para la mayoría de las funciones de CRT inseguras. Los tamaños de búfer para matrices estáticas se calculan automáticamente.

Aunque los búferes asignados dinámicamente no se arreglan de esta manera y necesitamos arreglarlos manualmente. Por favor, consulte este enlace para más detalles.

A continuación hay una manera de corregir su ejemplo programáticamente.

strcpy_s(extList->names[i], length, extName);


Usted sabe cuánto copiar, ¡le asignó espacio!

¿Seguramente usted no copiaría voluntariamente más del espacio que asignó?

Preferiría usar un método que evite explícitamente las saturaciones de búfer limitando el número de elementos copiados. De vuelta cuando era programador en C usábamos

dest = malloc(len); // note: where did we get len? if ( dest is null ) panic! // note: malloc can fail strncpy(dest, src, len); dest[len-1] =0;

Esto es un poco desordenado, y se ha señalado que está usando strncpy (), un método que realmente fue diseñado originalmente para campos de ancho fijo en lugar de cadenas. Sin embargo, sí lo hace

Hay métodos como strdup () y strlcpy () que podemos ayudar.

Mis recomendaciones:

1). Su objetivo no debería ser suprimir las advertencias, sino hacer que el código sea robusto.

2). Al copiar cadenas necesitas asegurarte de estas cosas:

  • Protéjase de una entrada incorrecta, por ejemplo, una cadena no terminada o excesivamente larga.
  • Protégete de los fallos de Malloc,
  • Prefiero las copias de números contados de caracteres a copiar hasta que veamos un nulo
  • Si reclamas construir una cadena, entonces asegúrate de que no termines

Si strlcpy () está disponible en su entorno, entonces podría usarlo, de lo contrario, ¿por qué no escribir su propia función de utilidad? Entonces, si hay advertencias en solo esa función que ha localizado, entonces el problema.


como se sugiere en el mensaje, use _CRT_SECURE_NO_WARNINGS para deshabilitar estas advertencias.

en ProjectProperties -> Propiedades de configuración -> C / C ++ -> Preprocesador -> Definiciones de preprocesador, agregue las siguientes macros:

_CRT_SECURE_NO_WARNINGS