Outros idiomas Deutsch ; English ; français ; Português brasileiro ; |
Sinopse: Esta página tem como objetivo ajudar você a reunir informações úteis quando ocorrer uma falha de software e talvez consertá-la sozinho. |
Contents
Preliminares
Primeiro, você deve instalar os pacotes -debug dos aplicativos e todas as bibliotecas que podem estar envolvidas. Isso permitirá que todas as ferramentas de depuração relatem informações mais úteis.
O próprio gdb lhe dará a linha de comando para executar a fim de instalar esses pacotes -debug e reiniciar o gdb
.
Agora você pode começar a coletar informações úteis usando as várias ferramentas listadas abaixo.
Para poder instalar pacotes -debug, você precisa adicionar ou habilitar os repositórios -debug separados. Se você adicionou um conjunto completo de repositórios via gerenciamento de software Mageia, tudo o que você precisa fazer é atualizá-los com o seguinte comando em um terminal como root:
# urpmi.update --no-ignore debug |
gdb
O programa gdb é o depurador GNU. Quando um programa trava devido a uma falha de segmentação ou um aborto, o gdb permitirá que você obtenha um backtrace, que é o lugar no programa onde o erro ocorreu.
Executando sua aplicação dentro do gdb
Se você puder reproduzir a falha facilmente, poderá executar seu aplicativo dentro do gdb e obter informações úteis quando a falha ocorrer.
- Inicie o gdb informando o caminho para seu aplicativo e diga para ele ser executado, se necessário, com os parâmetros.
- Se você receber mensagens sobre o sinal 33, você precisa dizer ao gdb para não parar nelas e passá-las para o aplicativo e, em seguida, reinicá-lo:
Program received signal SIG33, Real-time event 33. [Switching to Thread 1182845264 (LWP 11543)] 0x00002b661d87d536 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0 (gdb) handle SIG33 nostop noprint noignore pass Signal Stop Print Pass to program Description SIG33 No No Yes Real-time event 33 (gdb) kill Kill the program being debugged? (y or n) y (gdb) run |
- Quando o programa falhar, você receberá um prompt de gdb. Obter o backtrace com o comando
bt full
. Esta é a informação necessária no relatório de bugs. Se as mensagens anteriores falarem sobre tópicos, você deve obter todos os backtraces comthread apply all bt full
.
(gdb) bt full #0 0x00002b526953c7ef in poll () from /lib64/libc.so.6 No symbol table info available. #1 0x00002b52691f412e in g_main_context_iterate (context=0x51f2d0, block=1, dispatch=1, self=Variable "self" is not available.) at gc:2977 max_priority = 2147483647 timeout = 30000 some_ready = Variable "some_ready" is not available. |
Executando o gdb em um arquivo principal
Se por algum motivo você não conseguir reproduzir facilmente a falha dentro do gdb, mas tiver um arquivo principal, poderá fazer uma análise post-mortem. Por exemplo
$ gdb /bin/cat core.42 |
então, obtenha o backtrace com
thread apply all bt full
(Se nenhum núcleo é gerado após uma segfault, tente executar ulimit -c unlimited
no shell a partir do qual você vai iniciar o seu aplicativo).
Anexando o gdb a um aplicativo em execução
Depurar aplicativos com startups complexas, por exemplo, serviços de sistema, pode ser complicado, pois você pode não conhecer todos os parâmetros usados com o binário quando é lançado.
Nesses casos (assumindo que a falha não ocorra durante a inicialização), você pode anexar gdb a uma instância em execução do aplicativo.
Primeiro, identificar o processo em que a colisão ocorrerá, por exemplo, com
ps ax | grep //nome do aplicativo//
. Se o aplicativo estiver executando vários processos, tente notá-los todos, causando a falha e verificando o syslog para ver quais deles realmente falharam; quando você reiniciar o aplicativo, você pode anexar o gdb ao processo que ocupa o mesmo lugar relativo na lista.
Em seguida, anexar o gdb ao processo usando
gdb nome-do-executável id-do-processo
Isso fará com que o Gdb anexe a esse processo e o suspenda. Para retomar sua execução, use o comando
gdb c
.
Finalmente, cause o acidente, o que resultará em gdb informando sobre isso e colocando um prompt, no qual você pode solicitar um backtrace.
Se você tiver que executar o gdb de um tty, canalize a saída para um arquivo de texto (para que você possa anexá-lo a um relatório de bugs mais tarde). Isso pode ser feito usando o comando tee
, por exemplo:
gdb /bin/cat 2>&1 | tee logfile.txt
Isso salvará toda a saída para o logfile.txt. Quando você terminar, o arquivo de saída terá um registro de sua sessão de gdb.
Depuração do Apache no Mageia 2
Depurar o apache tornou-se problemático na Mageia 2. O script abaixo deve ser útil.
#!/bin/bash # debugging apache got broken with systemd in mga2, it used to be as easy as: # "/etc/rc.d/init.d/httpd stop; /etc/rc.d/init.d/httpd debug" # this script should do the trick. # Oden Eriksson <oeriksson@mandriva.com> /etc/rc.d/init.d/httpd stop defines=`/etc/rc.d/init.d/httpd show_defines` gdb /usr/sbin/httpd --batch --quiet -ex "run -f /etc/httpd/conf/httpd.conf -DNO_DETACH -DONE_PROCESS -DDEBUG $defines" -ex "thread apply all bt full" -ex "quit" |
strace
O programa strace listará todas as chamadas do sistema feitas pelo aplicativo (abra um arquivo, leia em um soquete de rede, ...) e isso pode ajudar a encontrar alguns problemas, como um arquivo ausente, um diretório não escredável... etc
Você pode executá-lo com
strace -f -o \\arquivo-de-saida\\ \\comando\\
por exemplo
strace -f -o ls.strace ls /tmp
executará ls /tmp
e salvar todas as chamadas do sistema para o arquivo ls.strace
ltrace
valgrind
Quando um programa é executado sob a supervisão de Valgrind, todas as leituras e gravações de memória são verificadas, e chamadas para malloc/new/free/delete são interceptadas. Como resultado, o Valgrind pode detectar problemas como:
- Utilização de memória não inicializada
- Ler/escrever a memória após de ter sido libertada
- Ler/escrever fora do final dos blocos malloc'd
- Ler/escrever áreas inapropriadas na pilha
- Vazamentos de memória - onde ponteiros para blocos malc'd são perdidos para sempre
- Passar de memória não-inicializada e/ou não endereçável às chamadas do sistema
- Uso incompatível de malloc/novo/novo [] vs livre/excluir/excluir []