como - valgrind c
Aún detectable Fuga detectada por Valgrind (4)
Todas las funciones mencionadas en este bloque son funciones de biblioteca. ¿Cómo puedo rectificar esta fuga de memoria?
Se encuentra en la categoría " Aún accesible ". (Hay 4 más, que son muy similares, pero de diferentes tamaños)
630 bytes in 1 blocks are still reachable in loss record 5 of 5
at 0x4004F1B: calloc (vg_replace_malloc.c:418)
by 0x931CD2: _dl_new_object (dl-object.c:52)
by 0x92DD36: _dl_map_object_from_fd (dl-load.c:972)
by 0x92EFB6: _dl_map_object (dl-load.c:2251)
by 0x939F1B: dl_open_worker (dl-open.c:255)
by 0x935965: _dl_catch_error (dl-error.c:178)
by 0x9399C5: _dl_open (dl-open.c:584)
by 0xA64E31: do_dlopen (dl-libc.c:86)
by 0x935965: _dl_catch_error (dl-error.c:178)
by 0xA64FF4: __libc_dlopen_mode (dl-libc.c:47)
by 0xAE6086: pthread_cancel_init (unwind-forcedunwind.c:53)
by 0xAE61FC: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126)
Captura: una vez que ejecuté mi programa, no dio pérdidas de memoria, pero tenía una línea adicional en la salida Valgrind, que no estaba presente antes:
Descartando syms en 0x5296fa0-0x52af438 en /lib/libgcc_s-4.4.4-20100630.so.1 debido a munmap ()
Si la fuga no se puede corregir, ¿alguien puede explicar al menos por qué la línea munmap () hace que Valgrind informe 0 "fugas" aún "alcanzables"?
Editar:
Aquí hay una muestra de prueba mínima:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *runner(void *param) {
/* some operations ... */
pthread_exit(NULL);
}
int n;
int main(void) {
int i;
pthread_t *threadIdArray;
n=10; /* for example */
threadIdArray = malloc((n+n-1)*sizeof(pthread_t));
for(i=0;i<(n+n-1);i++) {
if( pthread_create(&threadIdArray[i],NULL,runner,NULL) != 0 ) {
printf("Couldn''t create thread %d/n",i);
exit(1);
}
}
for(i=0;i<(n+n-1);i++) {
pthread_join(threadIdArray[i],NULL);
}
free(threadIdArray);
return(0);
}
Corre con:
valgrind -v --leak-check=full --show-reachable=yes ./a.out
Aquí hay una explicación adecuada de "todavía alcanzable":
"Todavía alcanzable" son fugas asignadas a variables globales y estáticas locales. Como valgrind rastrea las variables globales y estáticas, puede excluir las asignaciones de memoria que están asignadas "olvidar y olvidar". Una variable global asignó una asignación una vez y nunca reasignó esa asignación que normalmente no es una "fuga" en el sentido de que no crece indefinidamente. Todavía es una filtración en sentido estricto, pero generalmente puede ignorarse a menos que sea pedante.
Las variables locales asignadas y no libres son casi siempre filtraciones.
Aquí hay un ejemplo
int foo(void)
{
static char *working_buf = NULL;
char *temp_buf;
if (!working_buf) {
working_buf = (char *) malloc(16 * 1024);
}
temp_buf = (char *) malloc(5 * 1024);
....
....
....
}
Valgrind informará working_buf como "todavía alcanzable - 16k" y temp_buf como "definitivamente perdido - 5k".
Como hay alguna rutina de la familia pthread en la parte inferior (pero no conozco esa en particular), creo que ha lanzado un hilo como unible que ha terminado la ejecución.
La información de estado de salida de ese hilo se mantiene disponible hasta que llame a pthread_join
. Por lo tanto, la memoria se mantiene en un registro de pérdida al finalizar el programa, pero todavía es accesible ya que puede usar pthread_join
para acceder a ella.
Si este análisis es correcto, inicie estos subprocesos separados o únalos antes de finalizar su programa.
Editar : ejecuté su programa de muestra (después de algunas correcciones obvias) y no tengo errores, pero el siguiente
==18933== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
--18933--
--18933-- used_suppression: 2 dl-hack3-cond-1
--18933-- used_suppression: 2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a
Como la imagen se parece mucho a lo que ve, creo que ve un problema conocido que tiene una solución en términos de un archivo de supresión para valgrind
. Tal vez su sistema no esté actualizado, o su distribución no mantiene estas cosas. (El mío es ubuntu 10.4, 64 bits)
Hay más de una forma de definir "pérdida de memoria". En particular, hay dos definiciones principales de "pérdida de memoria" que son de uso común entre los programadores.
La primera definición comúnmente utilizada de "pérdida de memoria" es: "La memoria se asignó y no se liberó posteriormente antes de que finalizara el programa". Sin embargo, muchos programadores (con razón) argumentan que ciertos tipos de pérdidas de memoria que se ajustan a esta definición en realidad no plantean ningún tipo de problema, y por lo tanto no deberían considerarse verdaderas "fugas de memoria".
Una definición posiblemente más estricta (y más útil) de "pérdida de memoria" es: "La memoria se asignó y no se puede liberar posteriormente porque el programa ya no tiene punteros al bloque de memoria asignado". En otras palabras, no puede liberar memoria para la que ya no tiene punteros. Tal memoria es por lo tanto una "pérdida de memoria". Valgrind usa esta definición más estricta del término "pérdida de memoria". Este es el tipo de fuga que potencialmente puede causar un agotamiento de montón significativo, especialmente en procesos de larga duración.
La categoría "todavía alcanzable" dentro del informe de fugas de Valgrind se refiere a las asignaciones que se ajustan solo a la primera definición de "pérdida de memoria". Estos bloques no se liberaron, pero podrían haber sido liberados (si el programador hubiera querido) porque el programa todavía estaba haciendo un seguimiento de los indicadores a esos bloques de memoria.
En general, no hay necesidad de preocuparse por los bloques "todavía alcanzables". No plantean el tipo de problema que las pérdidas de memoria verdaderas pueden causar. Por ejemplo, normalmente no hay potencial para el agotamiento del montón de bloques "todavía alcanzables". Esto se debe a que estos bloques generalmente son asignaciones únicas, cuyas referencias se mantienen a lo largo de la duración de la vida del proceso. Si bien puede pasar y asegurarse de que su programa libere toda la memoria asignada, generalmente no hay ningún beneficio práctico al hacerlo, ya que el sistema operativo recuperará toda la memoria del proceso una vez que el proceso finalice. Contraste esto con fugas de memoria verdaderas que, si no se han corregido, podrían hacer que un proceso se quede sin memoria si se deja funcionando el tiempo suficiente o simplemente provocarán que un proceso consuma mucha más memoria de la necesaria.
Probablemente, el único momento en que sea útil asegurarse de que todas las asignaciones tengan "liberaciones" coincidentes es si sus herramientas de detección de fugas no pueden decir qué bloques son "todavía alcanzables" (pero Valgrind puede hacerlo) o si su sistema operativo no recupera todos la memoria de un proceso de terminación (todas las plataformas que Valgrind ha sido portado para hacer esto).
Parece que no entiendes lo que significa " still reachable
.
Todo lo que still reachable
no es una fuga. No necesitas hacer nada al respecto.