Pregunta

Estoy intentando depurar un problema de pérdida de memoria. Estoy usando mtrace () para obtener un malloc / free / realloc trace. He ejecutado mi programa y ahora tengo un archivo de registro enorme. Hasta ahora tan bueno. Pero tengo problemas para interpretar el archivo. Mira estas líneas:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502570 0x68
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502620 0x30
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1501460 0xa64

Lo extraño de esto es que una llamada (la misma dirección de retorno) es responsable de 4 asignaciones.

Incluso un extraño:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa2c
…
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80

Entre esas dos líneas, el bloque 0x2aaab43a1700 nunca se libera.

¿Alguien sabe cómo explicar esto? ¿Cómo podría uno dar como resultado 4 asignaciones? ¿Y cómo podría malloc devolver una dirección que ya estaba asignada anteriormente?

Editar 2008/09/30: La secuencia de comandos para analizar la salida de mtrace () proporcionada por GLIBC (mtrace.pl) no sirve de ayuda aquí. Simplemente dirá: Asigne 0x2aaab43a1700 duplicado. Pero, ¿cómo podría pasar esto?

¿Fue útil?

Solución

La función que está asignando la memoria se llama más de una vez. La dirección de la persona que llama apunta al código que hizo la asignación, y ese código simplemente se está ejecutando más de una vez.

Aquí hay un ejemplo en C:

void *allocate (void)
{
  return (malloc(1000));
}

int main()
{
  mtrace();
  allocate();
  allocate();
}

La salida de mtrace es:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000601460    0x3e8  at 0x4004f6
0x0000000000601850    0x3e8  at 0x4004f6

¿Observa cómo la dirección de la persona que llama es idéntica? Esta es la razón por la que el script de análisis mtrace dice que son idénticos, porque el mismo error se está viendo más de una vez, lo que produce varias fugas de memoria.

Compilar con marcas de depuración (-g) es útil si puedes:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000601460    0x3e8  at /home/andrjohn/development/playground/test.c:6
0x0000000000601850    0x3e8  at /home/andrjohn/development/playground/test.c:6

Otros consejos

Estás viendo la salida directa de mtrace, que es extremadamente confusa y contraintuitiva. Afortunadamente, hay un script en perl (llamado mtrace, que se encuentra dentro de glibc-utils) que puede ayudar fácilmente al análisis de esta salida.

Compile su compilación con la depuración activada, y ejecute mtrace como:

$ gcc -g -o test test.c
$ MALLOC_TRACE=mtrace.out ./test
$ mtrace test mtrace.out

Memory not freed:
-----------------
   Address     Size     Caller
0x094d9378    0x400  at test.c:6

La salida debería ser lot más fácil de digerir.

¿Una posible explicación es que la misma función es asignar diferentes tamaños de búfer? Un ejemplo es strdup.

Para la segunda pregunta, es posible que el tiempo de ejecución esté asignando algunos " static " Área de rayado que no está destinada a liberarse hasta que finalice el proceso. Y en ese momento, el sistema operativo se limpiará después del proceso de todos modos.

Piénsalo de esta manera: en Java, no hay destructores, y no hay garantías de que alguna vez se llame a la finalización de cualquier objeto.

Intenta ejecutar tu aplicación bajo valgrind. Podría darle una mejor vista de lo que realmente se está filtrando.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top