Así que he estado investigando cómo se implementa la parte stdio de libc y me he encontrado con otra pregunta. En cuanto a man setvbuf
I ver lo siguiente:¿Quién es el buffer setvbuf de free?
Cuando la primera operación I/O se produce en un archivo, malloc (3) se llama, y se obtiene un tampón .
Esto tiene sentido, su programa no debe tener un malloc
para E/S a menos que realmente lo use. Mi reacción instintiva es que libc limpiará su propio desorden aquí. Lo cual solo puedo suponer que lo hace porque valgrind informa que no hay pérdidas de memoria (por supuesto, podrían hacer algo sucio y no asignarlo vía malloc
directamente ... pero supondremos que literalmente usa malloc
por ahora).
Pero, puede especificar su propio buffer también ...
int main() {
char *p = malloc(100);
setvbuf(stdio, p, _IOFBF, 100);
puts("hello world");
}
Oh no, pérdida de memoria! valgrind lo confirma. Por lo tanto, parece que cada vez que stdio asigna un buffer por sí mismo, se eliminará automáticamente (a más tardar en la salida del programa, pero quizás en el cierre de la transmisión). Pero si especifica el búfer explícitamente, entonces debe limpiarlo usted mismo.
Sin embargo, hay una trampa. La página del manual también dice esto:
Debe asegurarse de que el espacio que puntos a BUF todavía existe cuando flujo está cerrado, que también pasa al acabarse el programa. Por ejemplo, el siguiente es inválido:
Ahora esto se está volviendo interesante para las transmisiones estándar. ¿Cómo podría uno limpiar correctamente un buffer asignado manualmente, ya que están cerrados en la terminación del programa? Podría imaginarse un "limpiar esto cuando cierro la bandera" dentro de la estructura de archivos, pero se ponen peludas porque si leo este derecho haciendo algo como esto:
setvbuf(stdout, 0, _IOFBF, 0);
printf("hello ");
setvbuf(stdout, 0, _IOLBF, 0);
printf("world\n");
causaría 2 asignaciones por la biblioteca estándar debido a esta oración:
Si el argumento buf es NULL, solo se ve afectado el modo ; un nuevo buffer será asignado en la siguiente operación de lectura o escritura .
EDIT: una adición a mi pregunta. Dado que está claro que debo free
cualquier buffers paso a setvbuf
, si de hecho lo uso en stdout
¿hay alguna forma práctica de free
? Debe vivir hasta el final del programa. Lo mejor que puedo pensar es en fclose(stdout)
y luego liberarlo o usar un buffer estático como algunas personas han mencionado. Lo pregunto porque parece una decisión de diseño incómoda.
Respuesta actualizada al enlace a la página. Es OS X, pero la página del manual proviene de FreeBSD (http://www.freebsd.org/cgi/man.cgi?query=setvbuf). – outis
Difícil ver cómo podrían ser las cosas de otra manera, ya que uno podría proporcionar un búfer estático que no se debe liberar con free(). –
@Neil: de hecho, me preguntaba más si el stdlib tenía una fuga de memoria por diseño, ya que no hay forma de obtener el búfer que asigna de la transmisión. –