2010-04-04 12 views
19

Estoy usando fopen en C para escribir el resultado en un archivo de texto. La declaración de la función es (donde ARRAY_SIZE se ha definido anteriormente):fopen/fopen_s y escribir en los archivos

void create_out_file(char file_name[],long double *z1){ 
    FILE *out; 
    int i; 

    if((out = fopen(file_name, "w+")) == NULL){ 
    fprintf(stderr, "***> Open error on output file %s", file_name); 
    exit(-1); 
    } 

    for(i = 0; i < ARRAY_SIZE; i++) 
    fprintf(out, "%.16Le\n", z1[i]); 
    fclose(out); 
} 

Mis preguntas:

  1. En recopilatorio con MVS2008 que recibo de la advertencia: Se advierte C4996: 'fopen': Esta función o variable puede ser inseguro Considera usar fopen_s en su lugar. No he visto mucha información en fopen_s para poder cambiar mi código. ¿Alguna sugerencia?

  2. ¿Se puede indicar fprintf para escribir números con la precisión numérica deseada en un archivo? Si estoy usando long double entonces supongo que mis respuestas son buenas hasta 15 dígitos después del punto decimal. ¿Estoy en lo cierto?

+16

No hay nada remotamente inseguro acerca de fopen(), pero algunas personas en MS parecen haber perdido sus mármoles colectivos sobre las funciones que toman cadenas terminadas en nulo como parámetros. –

+0

Creo que todo esto es una trama de Microsoft para bloquear a las personas en la programación solo de Windows. – stackptr

Respuesta

16

fopen_s es una variante de fopen que contiene la validación de parámetros y las manos hacia atrás un código de error en lugar de un puntero en caso de que algo va mal durante el proceso abierto. Es más seguro que la variante base porque representa más condiciones de borde. El compilador le advierte que lo use porque fopen representa un vector de explotación potencial en su aplicación.

Puede especificar dígitos de precisión a la printf familia de funciones utilizando el especificador %.xg, donde x son los dígitos de precisión que desee en la salida. Un long double varía en precisión de una plataforma a otra, pero en general se puede apostar a que tiene al menos 16 dígitos de precisión decimal.

Editar: Si bien no estoy totalmente a bordo con los otros que están sugiriendo que fopen_s es una pérdida completa de tiempo, representa una muy baja posibilidad de explotación y no se admite ampliamente. Algunas de las otras funciones advertidas bajo C4996 son vulnerabilidades mucho más serias, sin embargo, usar _CRT_SECURE_NO_WARNINGS es el equivalente a apagar la alarma tanto para "dejar la puerta de la habitación desbloqueada" como para "dejar una bomba nuclear en la cocina".

Siempre y cuando no esté limitado a usar "C puro" para su proyecto (p.para una asignación escolar o un microcontrolador integrado), haría bien en explotar el hecho de que casi todos los compiladores modernos de C son también compiladores C++ y usar las variantes C++ iostream de todas estas funciones de E/S para obtener una seguridad mejorada y compatibilidad al mismo tiempo.

+0

Gracias. Tengo fprintf (afuera, "% .16Le \ n", z1 [i]) en mi código y sí obtengo los 16 dígitos de precisión después del d.p. – yCalleecharan

+0

Gracias de nuevo. Estoy usando C ya que es lo que sé mejor. Estoy escribiendo un código para fines de investigación que debe dar resultados precisos. Tuve que no dimensionar mis ecuaciones formando el código C para tener un buen rango de valores que impidiera que los valores demasiado grandes o demasiado bajos no se arrastraran a la simulación y, por lo tanto, a la solución. No sé mucho sobre C++ y no sé si puedo guardar mi archivo en cpp y usar C++ iostream de manera segura sin que otras partes de mi código me den errores de compilación. Por ahora, me limitaré a C hasta que sepa cómo hacer el cambio a C++. – yCalleecharan

1

Simplemente defina _CRT_SECURE_NO_WARNINGS antes de incluir cualquier archivo para deshacerse de esta advertencia, y dejar de creer que lo que MS dice sobre fopen

+0

Gracias. ¿Es solo para agregar #define _CRT_SECURE_NO_WARNINGS en la parte superior? – yCalleecharan

6
  1. fopen_s y todos los demás _s funciones son MS-específica " seguras "variantes de funciones estándar. Si su código no necesita ser multiplataforma, puede simplemente cambiar y hacer feliz al compilador. De lo contrario, solo agregue la directiva de preprocesador _CRT_SECURE_NO_WARNINGS en la configuración de su proyecto y dejará de advertirle al respecto.

  2. Sí, el doble largo es fácilmente bueno para 15 dígitos de precisión; de hecho, incluso los dobles regulares son lo suficientemente buenos para eso (pero no más).

+0

Gracias. En mi máquina de 32 bits, tanto el doble como el doble largo me dan 16 dígitos de precisión y el decimosexto dígito es el que no es preciso. – yCalleecharan

+0

Sí, el tamaño 'largo doble' depende de la plataforma; lamentablemente, MSVC++ hace que sea lo mismo que 'double', por lo que realmente no sirve. Un doble de 64 bits tiene una precisión de 53 bits en la mantisa, que es aproximadamente 15.95 dígitos decimales (log10 (53)). – tzaman

+0

Gracias por la información. – yCalleecharan

4

Otros carteles han señalado que fopen no es realmente muy inseguro. Si no desea esta advertencia, pero desea las otras que advierten sobre vulnerabilidades reales, no #define _CRT_SECURE_NO_WARNINGS.

En su lugar, la próxima vez que reciba la advertencia de fopen, haga clic en la línea que dice "ver declaración de 'fopen'". Esto lo llevará a la línea en stdio.h que está inyectando la advertencia. Elimine el texto _CRT_INSECURE_DEPRECATE(fopen_s) de esa línea, y ya no recibirá la advertencia de seguridad cuando use fopen, pero se mantendrá para strcpy, strdup y esos otros posiblemente peligrosos.

+1

Actualmente en Windows, la implementación "estándar" de open tiene algunas vulnerabilidades debido a los 14, 125 y 16 años que no tienen nada mejor que hacer con su tiempo que encontrar formas de piratear programas y desordenar las computadoras de otras personas, por lo que se le ocurrió una forma diferente de pasar el descriptor de archivo que lo hace más difícil para los adolescentes – BrierMay

8

Me encontré con un problema similar al trabajar con Visual Studio 2012, pero donde se expandió mi problema fue que estoy construyendo un programa que quiero usar las características de Visual Studio para probar y finalmente poder compilar y ejecutar el misma aplicación en mi servidor Linux (estoy creando un bot)

así que esto es lo que se me ocurrió después de un poco de Google-ing y pensé en publicarlo en caso de que pudiera ayudar a alguien más.

FILE *fp_config; 
const char *configfile ; 
configfile = "bot.conf"; 
#ifdef WIN32 
    errno_t err; 
    if((err = fopen_s(&fp_config, configfile, "r")) !=0) { 
#else 
    if ((fp_config = fopen(configfile, "r")) == NULL) { 
#endif 
     fprintf(stderr, "Cannot open config file %s!\n", configfile); 
    } 

esto va a apaciguar a Visual Studio y no se quejará y también permitirá que el mismo código para compilar el gcc o cualquier otro estándar compatible con C/C++

4

Pasar de fopen a fopen_s deshabilitado la capacidad para abrir el archivo en el bloc de notas (solo lectura) mientras el archivo se abre y se escribe. Volviendo a fopen y puedo leer cómo mi programa escribe el archivo.

+0

De la [referencia] (http://en.cppreference.com/w/c/io/fopen): Cuando se usa fopen_s o freopen_s, archivo los permisos de acceso para cualquier archivo creado con "w" o "a" impiden que otros usuarios accedan a él.El indicador de modo de acceso a archivos "u" puede agregarse opcionalmente a cualquier especificador que comience con "w" o "a", para habilitar los permisos fopen predeterminados. (C11) –

Cuestiones relacionadas