Domanda

Sto provando a eseguire il debug di un problema di perdita di memoria. Sto usando mtrace () per ottenere una traccia malloc / free / realloc. Ho eseguito il mio programma e ora ho un enorme file di registro. Fin qui tutto bene. Ma ho problemi a interpretare il file. Guarda queste righe:

@ /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

La cosa strana è che una chiamata (stesso indirizzo di ritorno) è responsabile di 4 allocazioni.

Perfino straniero:

@ /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

Tra queste due righe il blocco 0x2aaab43a1700 non viene mai liberato.

Qualcuno sa come spiegarlo? In che modo una chiamata può comportare 4 allocazioni? E come potrebbe malloc restituire un indirizzo già assegnato in precedenza?

modifica il 30/09/2008: Lo script per analizzare l'output di mtrace () fornito da GLIBC (mtrace.pl) non è di alcun aiuto qui. Dirà solo: Alloc 0x2aaab43a1700 duplicato. Ma come è potuto succedere?

È stato utile?

Soluzione

La funzione che sta allocando la memoria viene chiamata più di una volta. L'indirizzo del chiamante punta al codice che ha eseguito l'allocazione e quel codice viene semplicemente eseguito più di una volta.

Ecco un esempio in C:

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

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

L'output di mtrace è:

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

Notare come l'indirizzo del chiamante è identico? Questo è il motivo per cui lo script di analisi mtrace sta dicendo che sono identici, perché lo stesso bug viene visto più di una volta, con conseguenti perdite di memoria.

La compilazione con flag di debug (-g) è utile se puoi:

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

Altri suggerimenti

Stai guardando l'output diretto di mtrace, che è estremamente confuso e controintuitivo. Fortunatamente, esiste uno script perl (chiamato mtrace, trovato in glibc-utils) che può aiutare molto facilmente l'analisi di questo output.

Compila la tua build con il debug attivo ed esegui mtrace in questo modo:

$ 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

L'output dovrebbe essere un lotto più facile da digerire.

Una possibile spiegazione è che la stessa funzione sta allocando dimensioni di buffer diverse? Uno di questi esempi è strdup.

Per la seconda domanda, è possibile che il runtime stia assegnando un po 'di "statico" area di lavoro che non è stata progettata per essere liberata fino al termine del processo. E a quel punto, il sistema operativo verrà comunque pulito dopo il processo.

Pensaci in questo modo: in Java non ci sono distruttori e nessuna garanzia che la finalizzazione sarà mai richiesta per nessun oggetto.

Prova a eseguire la tua app in valgrind. Potrebbe darti una visione migliore di ciò che viene effettivamente trapelato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top