Pergunta

Eu estou tentando depurar um problema de vazamento de memória. Estou usando mtrace () para obter a / livre traço malloc / realloc. Eu corri minha prog e tem agora um arquivo de log enorme. Por enquanto, tudo bem. Mas eu tenho problemas de interpretação do arquivo. Olhe para estas linhas:

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

O estranho nisso é que uma chamada (o mesmo endereço de retorno) é responsável por 4 alocações.

Ainda mais estranho:

@ /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 essas duas linhas do bloco 0x2aaab43a1700 nunca está sendo liberado.

Alguém sabe como explicar isso? Como se poderia chamar resultado em 4 alocações? E como poderia malloc retornar um endereço que já foi alocado anteriormente?

edição 2008/09/30: O script para analisar a saída mtrace () fornecida pelo GLIBC (mtrace.pl) não é de nenhuma ajuda aqui. Ela só vai dizer: Alloc 0x2aaab43a1700 duplicar. Mas como isso pôde acontecer?

Foi útil?

Solução

A função que está alocando a memória está sendo chamado mais de uma vez. O endereço chamador aponta para o código que fez a alocação, e que o código é simplesmente ser executado mais de uma vez.

Aqui está um exemplo em C:

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

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

A saída do mtrace é:

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

Observe como o endereço chamador é idêntico? É por isso que o script mtrace análise está dizendo que eles são idênticos, porque o mesmo bug está sendo visto mais que uma vez, resultando em vários vazamentos de memória.

Compilando com bandeiras depura (-g) é útil se você pode:

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

Outras dicas

Você está olhando para a saída direta de mtrace, que é extremamente confuso e contraditório. Felizmente, existe um script Perl (chamada mtrace, encontrado dentro glibc-utils), que pode facilmente ajudar a análise dessa produção.

Compilar sua compilação com depuração, e run mtrace como tal:

$ 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

A saída deve ser um muito mais fácil de digerir.

Uma explicação possível é que a mesma função é alocar diferentes tamanhos de buffer? Um exemplo é strdup.

Para a segunda pergunta, é possível que o tempo de execução está alocando alguns área de rascunho "estático", que não se destina a ser libertado até que o processo é encerrado. E nesse ponto, o sistema operacional irá limpar-se após o processo de qualquer maneira.

Pense nisso desta maneira:. Em Java, não há destruidores, e há garantias de que a finalização será sempre chamado para qualquer objeto

Tente executar o aplicativo sob valgrind. Pode dar-lhe uma melhor visão sobre o que está realmente a ser vazada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top