Uma funcionalidade muito útil em diversas linguagens de programação é a relacionada às ferramentas de debug, em que pode-se passar linha a linha pela execução de uma classe, arquivo ou script, verificando valores de variáveis, passagem de parâmetros, condições a serem seguidas e principalmente identificando pontos críticos em que algum comportamento estranho esteja acontecendo para que o programa não execute corretamente. A idéia deste artigo é apresentar a ferramenta perldebug para depurar scripts escritos em Perl.
Tudo começa na linha de comando, digitando algo como:
perl -d script.pl
Todas as bibliotecas são carregadas e a execução pára na primeira linha do script, esperando algum tipo de interação do usuário via terminal, indicando qual o próximo passo a ser seguido. O resultado nesse momento é algo como:
main::(script.pl:1):$a = "ABC";
DB<1>
O primeiro trecho indica qual o namespace sendo utilizado (nesse exemplo, o pacote padrão), qual o nome do script (script.pl), a linha corrente (no exemplo, a primeira) e qual a linha de código que está prestes a ser executada (mas que ainda não foi). Para que se passe para a próxima linha, basta digitar a tecla n (“next”) e apertar o enter.
A linha é executada e a interface é alterada para a próxima linha a ser executada:
main::(script.pl:8): usa_a
DB<2> p $a
Nesse ponto, pode-se desejar descobrir o valor de uma determinada variável ou expressão. Basta usar o comando p (“print”) e escrever o código desejado para imprimir o valor. No exemplo acima, será impresso o valor da variável $a.
Para entrar dentro de alguma chamada de função, usa-se o comando s (“sub”), mas caso não se queira fazer isso, basta apertar uma vez o comando n para que a execução da função seja transparente, passando ao próximo comando (ainda que o trecho associado à função tenha sido executado).
Para trechos de código mais longos ou para pontos específicos que seja necessário analisar, pode-se colocar “break points” através do comando b. Esse comando só possui um efeito mais poderoso quando usado em conjunto com o comando c (“continue”), executando todos os comandos até encontrar algum “break” e parando naquele ponto, esperando a próxima interação por parte do usuário. O uso do comando b deve vir associado com a linha em que ele deve parar ou então com o nome da função desejada. Em exemplos:
DB<3> b 111
DB<4> b nome_funcao
Nos dois exemplos, caso o fluxo de execução passe por um desses pontos, o terminal irá parar esperando que o próximo comando seja avaliado, seja ele passar para a próxima linha, seja um novo “continue”. A terceira opção do comando “break” é definir uma condição de parada, ou seja, o “break point” só será exercido caso a condição seja verdadeira:
DB<5> b 100 $a eq 10
Nesse exemplo, o fluxo de execução irá parar na linha 100 somente se a condição for satisfeita (se o valor de $a for igual a 10), caso contrário, não será feito nada. Esse tipo de opção é especialmente útil quando dentro de uma repetição, em que não se deseja passar por todas as passagens, mas apenas numa específica, segundo alguma informação de interesse.
Por último, vale lembrar que boa parte das funções prontas da linguagem também estão disponíveis para uso via terminal interativo e podem ser muito úteis. Um caso que merece destaque é a impressão de valores de uma coleção (vetor ou hash), para identificar se os valores estão de acordo com o esperado:
DB<6> p join(", ", keys %hash_teste)
DB<7> p join(", ", values %hash_teste)
DB<6> p join(", ", @vetor_teste)
No primeiro exemplo acima, serão impressas as chaves do %hash_teste separadas por vírgula e espaço. No segundo, serão impressos apenas os valores. Já no terceiro, todos os elementos do @vetor_teste.