Fuga aún accesible detectada por Valgrind

Resuelto asked hace 14 años • 5 respuestas

Todas las funciones mencionadas en este bloque son funciones de biblioteca. ¿Cómo puedo rectificar esta pérdida de memoria?

Aparece en la categoría " Aún accesible ". (Hay 4 más, que son muy similares, pero de distintos 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 hubo pérdidas de memoria, pero tenía una línea adicional en la salida de 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 rectificar, ¿alguien puede al menos explicar por qué la línea munmap() hace que Valgrind informe 0 fugas "aún accesibles"?

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
 avatar Oct 01 '10 22:10
Aceptado

Hay más de una forma de definir "pérdida de memoria". En particular, existen 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 deben considerarse verdaderas "pérdidas de memoria".

Podría decirse que una definición 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 ningún puntero al bloque de memoria asignado". En otras palabras, no puedes liberar memoria a la que ya no tienes ningún indicador. Por tanto, dicha memoria es una "pérdida de memoria". Valgrind utiliza esta definición más estricta del término "pérdida de memoria". Este es el tipo de fuga que potencialmente puede provocar un agotamiento significativo del montón, especialmente en procesos de larga duración.

La categoría "aún accesible" dentro del informe de fugas de Valgrind se refiere a asignaciones que sólo se ajustan a la primera definición de "pérdida de memoria". Estos bloques no fueron liberados, pero podrían haberse liberado (si el programador hubiera querido) porque el programa todavía estaba realizando un seguimiento de los punteros a esos bloques de memoria.

En general, no hay necesidad de preocuparse por los bloques "aún accesibles". No plantean el tipo de problema que pueden causar las verdaderas pérdidas de memoria. Por ejemplo, normalmente no existe la posibilidad de que se agote el montón debido a bloques "aún accesibles". Esto se debe a que estos bloques suelen ser asignaciones únicas, cuyas referencias se mantienen durante toda la vida del proceso. Si bien puede revisar y asegurarse de que su programa libere toda la memoria asignada, generalmente no hay ningún beneficio práctico al hacerlo ya que, de todos modos, el sistema operativo recuperará toda la memoria del proceso una vez que finalice el proceso. Compare esto con las verdaderas pérdidas de memoria que, si no se solucionan, podrían provocar que un proceso se quede sin memoria si se deja funcionando durante un tiempo suficiente, o simplemente provocarán que un proceso consuma mucha más memoria de la necesaria.

Probablemente el único momento en el que sea útil garantizar que todas las asignaciones tengan "libres" coincidentes es si sus herramientas de detección de fugas no pueden determinar qué bloques son "todavía accesibles" (pero Valgrind puede hacerlo) o si su sistema operativo no reclama todos los la memoria de un proceso de terminación (todas las plataformas en las que Valgrind ha sido adaptado para hacer esto).

Dan Moulding avatar Oct 04 '2010 17:10 Dan Moulding

Dado que hay alguna rutina de la familia pthread en la parte inferior (pero no conozco cuál en particular), supongo que ha iniciado algún hilo que se puede unir y que ha finalizado la ejecución.

La información del estado de salida de ese hilo se mantiene disponible hasta que usted llame pthread_join. Por lo tanto, la memoria se mantiene en un registro de pérdida al finalizar el programa, pero aún es accesible ya que podría utilizarla pthread_joinpara acceder a ella.

Si este análisis es correcto, inicie estos subprocesos separados o únase a ellos antes de finalizar su programa.

Editar : ejecuté su programa de muestra (después de algunas correcciones obvias) y no tengo errores, excepto los siguientes

==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

Dado que la dl-cosa se parece mucho a lo que ves, supongo que ves un problema conocido que tiene una solución en términos de un archivo de supresión para valgrind. Quizás su sistema no esté actualizado o su distribución no mantenga estas cosas. (El mío es ubuntu 10.4, 64 bits)

Jens Gustedt avatar Oct 04 '2010 16:10 Jens Gustedt