5. Depuração e Perfilagem

5.1. Manutenção Preventiva (lint)

Não existe qualquer lint largamente usado em Linux, como a maioria das pessoas está satisfeita com os avisos que o gcc pode gerar. Provavelmente a mais útil é a opção -Wall --- isto significa `Warnings, all' (`avisos, todos') mas provavelmemte tem mais valor mnemônico se considerado como a coisa contra a qual você bate a sua cabeça.

Existe um lint de domínio público disponível em . Eu não sei quão boa ele é.

5.2. Depuração

5.2.1. Como eu obtenho informação de depuração em um programa?

Você precisa compilar e linkar todas as partes com a opção -g, e sem a opção -fomit-frame-pointer. Na verdade, você não precisa recompilar tudo, somente as partes que você quer depurar.

Em configurações a.out as bibliotecas compartilhadas são compiladas com -fomit-frame-pointer, com a qual o gdb não trabalha. Usar a opção -g ao linkar deveria implicar em uma linkagem estática; esta é a razão.

Se o linker falha com uma mensagem avisando que não encontra libg.a, você não tem /usr/lib/libg.a, que é a biblioteca C especial para depuração. Ela pode ser fornecida com o pacote binário da libc, ou (em versões mais novas da biblioteca C) você pode precisar obter o código fonte da libc e construí-la você mesma. Você não precisa realmente dela entretanto; você pode obter informação suficiente para a maioria dos propósitos apenas fazendo um link simbólico, dela para /usr/lib/libc.a

5.2.1.1. Como removê-las?

Uma grande quantidade de software GNU vêm configurada para compilar e linkar com -g, causando a geração de executáveis muito grandes (e frequentemente estáticos) Esta não é realmente uma boa idéia.

Se o programa tem um script configure gerado por autoconf, usualmente você pode desativar a informação de depuração fazendo ./configure CFLAGS= ou ./configure CFLAGS=-O2. De outra forma, verifique o arquivo Makefile. É claro que, se você está usando ELF, o programa é linkado dinamicamente com ou sem a opção -g, de forma que você pode apenas remove-la.

5.2.2. Software disponível

A maioria das pessoas usa gdb, o qual você pode obter, na forma de fonte, dos sites de arquivos GNU, ou como um binário em tsx-11 ou sunsite. xxgdb é um depurador para X baseado nele (isto é, você precisa ter gdb instalado primeiro). Os fontes podem ser encontrados em

Além disso, o depurador UPS foi portado por Rick Sladkey. Ele executa sob X também, mas ao contrário de xxgdb, ele não é meramente um front-end X para um depurador baseado em texto. Ele tem um bom número de características agradáveis, e se você gasta muito tempo depurando coisas, você provavelmente deve testá-lo. A versão pré-compilada para Linux e correções para o fontes do UPS padrão podem ser encontradas em , e o fonte original em .

Uma outra ferramente que você pode achar útil para depuração é `strace', a qual exibe as chamadas de sistema que um processo executa. Ele tem uma multiplicidade de outros usos também, incluindo a obtenção dos nomes dos arquivos, com os respectivos caminhos, que foram compilados em binários dos quais você não tem o fonte, agravamento de condições de corrida em programas que você suspeita que as contenha e, de forma geral, aprender como as coisas funcionam. A versão mais recente do strace (correntemente 3.0.8) pode ser encontrada em .

5.2.3. Programas de background (daemon)

Programas daemon tipicamente executam fork() logo após iniciar, e finalizam o programa pai. Isto leva a uma curta sesão de depuração.

A forma mais simples de contornar isto é definir um breakpoint para fork, e quando o programa parar, forçá-lo a retornar 0.

    (gdb) list
    1       #include <stdio.h>
    2
    3       main()
    4       {
    5         if(fork()==0) printf("child\n");
    6         else printf("parent\n");
    7       }
    (gdb) break fork
    Breakpoint 1 at 0x80003b8
    (gdb) run
    Starting program: /home/dan/src/hello/./fork
    Breakpoint 1 at 0x400177c4
    
    Breakpoint 1, 0x400177c4 in fork ()
    (gdb) return 0
    Make selected stack frame return now? (y or n) y
    #0  0x80004a8 in main ()
        at fork.c:5
    5         if(fork()==0) printf("child\n");
    (gdb) next
    Single stepping until exit from function fork,
    which has no line number information.
    child
    7       }


5.2.4. Arquivos core

Quando o Linux inicializa ele é configurado, usualmente, para não produzir arquivos core. Se você gosta deles, use o comando nativo do seu shell para reativá-los: para shells compatíveis com C-shell (por exemplo, tcsh) isto é

    % limit core unlimited
enquanto que para shells do tipo Bourne (sh, bash, zsh, pdksh) use
    $ ulimit -c unlimited


Se você quer um pouco mais de versatilidade na nomeação dos seus arquivos core (por exemplo, se você está tentando realizar uma análise post-mortem usando um depurador que também tem bugs) você pode fazer uma modificação simples no seu kernel. Procure o código em fs/binfmt&lowbar;aout.c e fs/binfmt&lowbar;elf.c (em kernels mais novos, você terá pesquisar um pouco, com grep, em versões mais antigas) que diz

            memcpy(corefile,"core.",5);
    #if 0
            memcpy(corefile+5,current->comm,sizeof(current->comm));
    #else
            corefile[4] = '\0';
    #endif


e mude os 0s para 1s.

5.3. Perfilagem

Perfilagem é uma mameira de examinar quais partes do programa são chamadas mais freqüentemente ou executam por mais tempo. É uma boa maneira de otimizar código e descobrir onde se está desperdiçando tempo. Você deve compilar todos os arquivos objeto dos quais você quer informação de tempo com -p, e para entender o arquivo de saída você também vai precisar de gprof (do pacote binutils). Veja a página de manual do gprof para detalhes.