Fuga todavía alcanzable detectada por Valgrind


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 " Todavía 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)

Catch: Una vez que ejecuté mi programa, no dio fugas de memoria, pero tenía una línea adicional en la salida de Valgrind, que no estaba presente antes:

Descartar syms en 0x5296fa0-0x52af438 en / lib / libgcc_s-4.4.4-20100630.so. 1 debido a munmap ()

Si la fuga no puede ser rectificada, ¿puede alguien al menos explicar por qué la línea munmap() hace que Valgrind reporte 0 fugas "aún accesibles"?

Editar:

Aquí hay una muestra mínima de prueba:

#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);
}

Ejecutar con:

valgrind -v --leak-check=full --show-reachable=yes ./a.out
Author: Dan Moulding, 2010-10-01

4 answers

Hay más de una forma de definir "fuga de memoria". En particular, hay dos definiciones principales de" fuga de memoria " que son de uso común entre los programadores.

La primera definición comúnmente utilizada de "fuga de memoria" es, "La memoria fue asignada y no fue liberada posteriormente antes de que el programa terminara."Sin embargo, muchos programadores (con razón) argumentan que ciertos tipos de fugas de memoria que se ajustan a esta definición en realidad no plantean ningún tipo de problema, y por lo tanto no deben ser considerado verdadero "fugas de memoria".

Una definición posiblemente más estricta (y más útil) de "fuga de memoria" es, "La memoria fue asignada y no puede ser liberada posteriormente porque el programa ya no tiene ningún puntero al bloque de memoria asignado."En otras palabras, no se puede liberar la memoria que ya no tiene ningún indicador. Tal memoria es, por lo tanto, una "fuga de memoria". Valgrind utiliza esta definición más estricta del término "fuga de memoria". Este es el tipo de fuga que puede potencialmente causar un agotamiento significativo del montón, especialmente para procesos de larga vida.

La categoría "todavía accesible" dentro del informe de fugas de Valgrind se refiere a asignaciones que se ajustan solo a la primera definición de "fuga de memoria". Estos bloques no fueron liberados, pero podrían haber sido liberados (si el programador hubiera querido) porque el programa todavía estaba llevando un registro 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 true las fugas de memoria pueden causar. Por ejemplo, normalmente no hay potencial para el agotamiento del montón de bloques "todavía accesibles". Esto se debe a que estos bloques generalmente son asignaciones de una sola vez, las referencias a las cuales se mantienen durante toda la duración de la vida útil del proceso. Si bien puede pasar y asegurarse de que su programa libera toda la memoria asignada, generalmente no hay ningún beneficio práctico de hacerlo, ya que el sistema operativo recuperará todo de la memoria del proceso después de que el proceso termina, de todos modos. Contrasta esto con true las fugas de memoria que, si se dejan sin fijar, podrían causar que un proceso se quede sin memoria si se deja funcionando el tiempo suficiente, o simplemente causarán que un proceso consuma mucha más memoria de la necesaria.

Probablemente la única vez que sea útil asegurarse de que todas las asignaciones tengan "frees" coincidentes sea si sus herramientas de detección de fugas no pueden decir qué bloques son "aún accesibles" (pero Valgrind puede hacer esto) o si su el sistema operativo no recupera toda la memoria de un proceso de terminación (todas las plataformas que Valgrind ha sido portado para hacer esto).

 287
Author: Dan Moulding,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-04 17:30:19

Dado que hay alguna rutina de la familia pthread en la parte inferior (pero no conozco esa en particular), mi conjetura sería que has lanzado algún hilo como joinable 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 podría usar pthread_join para acceder a ella.

Si este análisis es correcto, inicie estos hilos separados, o unirse a ellos antes de terminar el programa.

Edit: Ejecuté su programa de muestra (después de algunas correcciones obvias) y no tengo errores, pero 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 cosa dl- 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. Tal vez su sistema no está actualizado, o su distribución no mantiene estas cosas. (El mío es ubuntu 10.4, 64bit)

 10
Author: Jens Gustedt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-04 18:58:58

No parece entender lo que still reachable significa.

Cualquier cosa still reachable es no una fuga. No necesitas hacer nada al respecto.

 7
Author: Employed Russian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-03 17:20:51

Aquí hay una explicación adecuada de"todavía accesible":

"Still reachable" son filtraciones asignadas a variables globales y estáticas locales. Debido a que valgrind rastrea variables globales y estáticas, puede excluir asignaciones de memoria que se asignan "una vez y olvidarse". Una variable global asignada una asignación una vez y nunca reasignada esa asignación no es típicamente una "fuga" en el sentido de que no crece indefinidamente. Todavía es una fuga en el sentido estricto, pero generalmente se puede ignorar a menos que seas pedante.

Las variables locales a las que se asignan asignaciones y no se liberan casi siempre son fugas.

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 reportará working_buf como "still reachable - 16k" y temp_buf como "definitely lost - 5k".

 2
Author: Abbey Road,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-15 19:36:56