c++ - manejo - ¿Por qué no puedo usar fopen?
manejo de archivos en c ejemplos (6)
En el molde de una pregunta anterior que pregunté sobre las llamadas depreciaciones de bibliotecas seguras , me parece igualmente desconcertado por qué fopen()
debe ser desaprobado.
La función toma dos cadenas C y devuelve un ARCHIVO * ptr, o NULL en caso de error. ¿Dónde están los problemas de seguridad de los hilos / problemas de desbordamiento de la cadena? ¿O es otra cosa?
Gracias por adelantado
¿O es otra cosa?
Algunas implementaciones de la estructura de ARCHIVOS utilizadas por ''fopen'' tienen el descriptor de archivo definido como ''corto sin signo''. Esto te deja con un máximo de 255 archivos abiertos simultáneamente, menos stdin, stdout y stderr.
Si bien el valor de tener 255 archivos abiertos es discutible, por supuesto, ¡este detalle de implementación se materializa en la plataforma Solaris 8 cuando tiene más de 252 conexiones de socket ! Lo que apareció por primera vez como un fallo aparentemente aleatorio para establecer una conexión SSL con libcurl en mi aplicación resultó ser causado por esto, pero tomó la implementación de versiones de depuración de libcurl y openssl y pisando al cliente a través del script de depuración para finalmente resolverlo.
Si bien no es totalmente culpa de ''fopen'', uno puede ver las virtudes de deshacerse de los grilletes de las interfaces antiguas; La opción de desaprobar podría basarse en el dolor de mantener la compatibilidad binaria con una implementación anticuada.
Existe un informe técnico oficial de ISO / IEC JTC1 / SC22 / WG14 (Idioma C) TR24731-1 (interfaces de verificación de límites) y su justificación está disponible en:
También hay trabajo hacia TR24731-2 (funciones de asignación dinámica).
La justificación indicada para fopen_s()
es:
6.5.2 Funciones de acceso a archivos
Al crear un archivo, las funciones
fopen_s
yfreopen_s
mejoran la seguridad al proteger el archivo del acceso no autorizado al configurar su protección de archivos y abrir el archivo con acceso exclusivo.
La especificación dice:
6.5.2.1 La función fopen_s
Sinopsis
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
errno_t fopen_s(FILE * restrict * restrict streamptr,
const char * restrict filename,
const char * restrict mode);
Restricciones de tiempo de ejecución
Ninguno de streamptr
, filename
o mode
será un puntero nulo.
Si hay una violación de restricción de tiempo de ejecución, fopen_s
no intenta abrir un archivo. Además, si streamptr
no es un puntero nulo, fopen_s
establece *streamptr
en el puntero nulo.
Descripción
La función
fopen_s
abre el archivo cuyo nombre es la cadena a la que apunta elfilename
defilename
y asocia una secuencia con él.La cadena de modo será como se describe para
fopen
, con la adición de que los modos que comienzan con el carácter ''w'' o ''a'' pueden estar precedidos por el carácter ''u'', consulte a continuación:
uw
truncar a longitud cero o crear un archivo de texto para escribir, permisos predeterminadosua
anexar abrir o crear un archivo de texto para escribir al final del archivo, permisos predeterminadosuwb
trunca a longitud cero o crea un archivo binario para escribir, permisos predeterminados- añadir
uab
abrir o crear un archivo binario para escribir al final del archivo, permisos predeterminadosuw+
truncar a longitud cero o crear un archivo de texto para actualizar, permisos predeterminadosua+
añadir; abrir o crear un archivo de texto para actualizar, escribir al final del archivo, permisos predeterminadosuw+b
ouwb+
truncan a longitud cero o crean un archivo binario para la actualización, permisos predeterminadosua+b
ouab+
anexar; abrir o crear un archivo binario para actualizar, escribir al final del archivo, permisos predeterminadosEn la medida en que el sistema subyacente sea compatible con los conceptos, los archivos abiertos para escritura se abrirán con acceso exclusivo (también conocido como no compartido). Si se está creando el archivo y el primer carácter de la cadena de modo no es ''u'', en la medida en que el sistema subyacente lo admita, el archivo tendrá un permiso de archivo que impide que otros usuarios en el sistema accedan al archivo. Si el archivo se está creando y el primer carácter de la cadena de modo es ''u'', entonces, cuando se cierre el archivo, tendrá los permisos de acceso a archivos predeterminados del sistema 10) .
Si el archivo se abrió con éxito, entonces el puntero a
FILE
apuntado porstreamptr
se establecerá en el puntero al objeto que controla el archivo abierto. De lo contrario, el puntero aFILE
apuntado porstreamptr
se establecerá en un puntero nulo.Devoluciones
La función
fopen_s
devuelve cero si abrió el archivo. Si no abrió el archivo o si hubo una violación de restricción de tiempo de ejecución,fopen_s
devuelve un valor distinto de cero.10) Estos son los mismos permisos con los que el archivo habría sido creado por fopen.
Hilo de seguridad. fopen()
utiliza una variable global, errno
, mientras que el reemplazo fopen_s()
devuelve un errno_t
y toma un argumento FILE**
para almacenar el puntero del archivo.
Las nuevas versiones hacen validación de parámetros mientras que las anteriores no lo hicieron.
Vea este subproceso SO para más información.
Microsoft ha agregado la función fopen_s()
al tiempo de ejecución de C con las siguientes diferencias fundamentales de fopen()
:
- Si el archivo se abre para escritura ("w" o "a" especificado en el modo), entonces el archivo se abre para acceso exclusivo (no compartido) (si la plataforma lo admite).
- Si se usa el especificador "u" en el argumento de modo con los especificadores "w" o "a", entonces, cuando se cierre el archivo, tendrá permisos predeterminados del sistema para que otros usuarios accedan al archivo (lo que puede no estar disponible). acceso si ese es el sistema por defecto).
- Si la "u" especificada no se usa en esos casos, entonces, cuando el archivo se cierre (o antes), los permisos para el archivo se establecerán de tal manera que otros usuarios no tengan acceso al archivo.
Básicamente, significa que los archivos que escribe la aplicación están protegidos de otros usuarios de forma predeterminada.
No le hicieron esto a fopen()
debido a la probabilidad de que el código existente se rompiera.
Microsoft ha optado por dejar de usar fopen()
para alentar a los desarrolladores de Windows a tomar decisiones conscientes sobre si los archivos que usan sus aplicaciones tendrán permisos sueltos o no.
La respuesta de Jonathan Leffler proporciona el lenguaje de estandarización propuesto para fopen_s()
. Agregué esta respuesta con la esperanza de aclarar la razón.
Puedes usar fopen()
. En serio, no hagas caso de Microsoft aquí, les están haciendo un mal servicio a los programadores al desviarse de los estándares ISO. Parece que piensan que las personas que escriben código tienen alguna muerte cerebral y no saben cómo verificar los parámetros antes de llamar a las funciones de la biblioteca.
Si alguien no está dispuesto a aprender las complejidades de la programación en C, realmente no tiene nada que hacer. Deben pasar a un lenguaje más seguro.
Esto parece ser solo otro intento de bloqueo de proveedores por parte de los desarrolladores de Microsoft (aunque no son los únicos que lo intentan, así que no los estoy reprendiendo específicamente). Normalmente agrego:
#define _CRT_SECURE_NO_WARNINGS
(o la variante "-D"
en la línea de comandos) a la mayoría de mis proyectos para asegurar que el compilador no me moleste al escribir el código C legalmente válido.
Microsoft ha proporcionado funcionalidad adicional en la función fopen_s()
(codificaciones de archivos, por ejemplo), además de cambiar cómo se devuelven las cosas. Esto puede hacer que sea mejor para los programadores de Windows, pero hace que el código sea intrínsecamente no portátil.
Si solo vas a codificar para Windows, por supuesto, úsalo. Yo mismo prefiero la capacidad de compilar y ejecutar mi código en cualquier lugar (con el menor cambio posible).
A partir de C11, estas funciones seguras ahora forman parte de la norma, aunque son opcionales. Mire en el Anexo K para más detalles.