supera - ¿Free() establece errno?
maxjsonlength exception in asp net mvc during javascriptserializer (5)
No se dice nada acerca de
errno
en la descripción de
free
en el Estándar C.
Por lo tanto, es posible que no confíe en esta función.
De acuerdo con el estándar C (7.5 errores
<errno.h>
)
3 ... El valor de errno puede establecerse en distinto de cero mediante una llamada de función de biblioteca, haya o no un error, siempre que el uso de errno no esté documentado en la descripción de la función en esta Norma Internacional.
Y el uso de
errno
no está documentado en la descripción de
free
en el Estándar C como ya he dicho anteriormente.
Si
buf
es un búfer de caracteres asignado
malloc()
, ¿
free(buf)
establece / restablece
errno
?
Digamos que quiero escribir el búfer en un archivo y luego liberarlo, ya que no lo necesito más.
Digamos que la política de error para el código es devolver -1 en caso de error.
¿Es esta una forma adecuada de escribir el búfer y la verificación de errores sin pérdida de memoria?
fputs(buf, somefile);
free(buf);
if (errno) return -1;
¿O debo considerar la posibilidad de configurar errno de forma gratuita, como en ...
fputs(buf, somefile);
if (errno){
free(buf);
return -1;
}
free(buf);
o, horror de los horrores,
do {
fputs(buf, somefile);
int save_errno = errno;
free(buf);
errno = save_errno;
if (errno) return -1;
} while(0);
donde el uso de un bloque permite que exista un save_errno local en varios lugares en caso de que sea necesario reutilizarlo.
Todo esto parece depender de si free () establece errno.
La
página de manual de Linux para free ()
también es la página de manual para
malloc()
, etc. Menciona la configuración de
malloc()
errno, pero no
free()
.
La página del manual de la Biblioteca GNU C para liberar memoria dinámica no menciona si free () establece errno.
Entonces escribí un programa corto para forzar un error de escritura para poder ver si free () restablece errno, y no lo hace. Me pregunto si debería confiar en este resultado y en el hecho de que free () es tan esencial que "por supuesto que no establece errno".
# See if free() resets errno on a bad write
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
char * buf = malloc(256);
snprintf(buf,256,"%s/n", "Hello, World!");
FILE *badfile;
badfile = fopen("/dev/null","r");
fputs(buf, badfile);
free(buf);
printf("%d/n", errno);
printf("%s/n", strerror(errno));
}
POSIX no define
free
errno
(aunque POSIX no lo prohíbe actualmente, por lo que una implementación podría hacerlo; consulte
la respuesta de @ ArjunShankar
para obtener más detalles).
Pero eso no es realmente relevante para su preocupación.
La forma en que está buscando errores es incorrecta.
Debe verificar el valor de retorno de
fputs
y verificar si es menor que
0
.
Si es así, puede verificar
errno
para averiguar qué causó la falla, pero eso es opcional (y debe hacerse antes de llamar a otras funciones).
Entonces, algo como esto debería hacer el truco:
int result = fputs(buf, somefile);
/* optionally read errno here if result < 0 (before the free call) */
free(buf);
return (result < 0) ? -1 : 0;
Si la referencia no dice que una función devuelve un código de error en
errno
en caso de falla, no lo hará.
Las funciones que configuran
errno
en un código de error (casi) siempre indican de otra manera que
errno
contiene el código de error actual: las funciones de asignación de memoria devuelven
NULL
, muchas otras funciones devuelven cero o un número negativo, y así sucesivamente.
Dichas funciones no requieren modificar
errno
de ninguna manera si tienen éxito, y generalmente no lo hacen.
Por lo general, no puede inspeccionar
errno
para determinar si algo salió mal;
solo está destinado a recuperar más información una vez que sepa que ha habido un error.
Una excepción a la regla final es la
strto{l, d, ul}
, pero el primer párrafo también es cierto para aquellos.
Y tampoco establecen necesariamente
errno
excepto cuando fallan, por lo que debe borrarlo primero o puede contener un código de error obsoleto.
Un programa
free
compatible con POSIX podría
errno
hoy,
pero esto va a cambiar para mejor en el futuro.
Detalles:
-
La definición de
errno
de The Open Group Base Especificaciones Issue 7 establece lo siguiente:
Ninguna función en este volumen de POSIX.1-2008 establecerá errno en 0. La configuración de errno después de una llamada exitosa a una función no se especifica a menos que la descripción de esa función especifique que errno no se modificará.
-
La definición de
free
sí no especifica qué hacefree
conerrno
.
Lo que esto significa es que una implementación
free
compatible nunca restablecerá
errno
a 0. Pero puede establecerlo o no en un valor distinto de cero.
Sin embargo, el número 8 (un trabajo en progreso) de la especificación
requerirá
free
para garantizar específicamente que no se establecerá
errno
cuando se pase una entrada válida.
glibc ya se está preparando para cumplir con este nuevo requisito.
puede usar RAII para liberar memoria mal asignada y verificar el valor de retorno de fputs. Ese será el código de gracia.
//if malloc successfully
AutoFree af(buf);
if (fputs(buf, somefile)) {
LOG("something err:%s", strerror(errno));
}
return 0;