Desenvolvimento - C/C++

Usando o debugador do Visual C++ 6.0

Bugs e erros são uma constante na vida de qualquer programador. Por melhor que seja a análise realizada antes da implementação, é fato que qualquer programa recém escrito terá algum erro escondido esperando para aparecer quando menos se espera. Assim, darei inicio à uma série de tutoriais que visa auxiliar a esta árdua e ingrata tarefa de corrigir programas. Os primeiros artigos tratarão de ferramentas auxiliares de debugação, sendo seguidos posteriormente por técnicas de programação para tratar de erros já com o programa sendo utilizado. Boa leitura!

por Adenilson Cavalcanti da Silva



Bugs e erros são uma constante na vida de qualquer programador. Por melhor que seja a análise realizada antes da implementação, é fato que qualquer programa recém escrito terá algum erro escondido esperando para aparecer quando menos se espera. Assim, darei inicio à uma série de tutoriais que visa auxiliar a esta árdua e ingrata tarefa de corrigir programas. Os primeiros artigos tratarão de ferramentas auxiliares de debugação, sendo seguidos posteriormente por técnicas de programação para tratar de erros já com o programa sendo utilizado. Boa leitura!

Introdução

Programas escritos em linguagem C sempre foram tidos como problemáticos, no sentido de eliminar erros de lógica como os temidos ponteiros selvagens. Em tempos não tão remotos, era comum o programador se ver obrigado a encher o código com mensagens de saída para impressão dos valores das variáveis ou mesmo ir gravando os valores temporários de um dado algoritmo em arquivos externos até o momento em que o erro aparecesse.

Felizmente, contamos na atualidade com ferramentas poderosas de debugação, que permitem de forma visual examinar um programa em execução e conferir o estado de variáveis e classes. O propósito deste artigo é apresentar os recursos básicos de debugação do ambiente de desenvolvimento Visual C++ 6.0. Para tanto, será criado um pequeno programa para examine durante o artigo, que cuida de leitura e escrita de arquivos e um processamento básico.

Estudo de caso

O programa que será utilizado para estudo é composto por 3 arquivos fonte, onde a função principal chama os procedimentos dos outros arquivos para realizar a tarefa: leitura de dados de um arquivo texto, cálculo do volume a partir dos dados fornecidos e finalmente gravação de um arquivo de saída com estes resultados.

A organização do programa é apresentada na figura abaixo:

Organização do programa

Figura 1: Organização do programa

O módulo principal é representado pela função "main", sendo responsável pela abertura do arquivo de dados e pela gravação do arquivo com os volumes. A leitura do arquivo de entrada é realizada pelo módulo "Cargaarq", que recebe um ponteiro para o arquivo aberto bem como uma referência para o vetor onde os dados devem ser gravados. Como os dados são compostos por diâmetro e altura, estes são armazenados em uma estrutura com 2 campos como segue:

Listagem 1:Exemplo de struct

struct Data
{
float DAP;
int Altura;
};

O cálculo de volume é processado pelo módulo "Calcula volume", sendo composto por apenas 1 função: "Calcvol". Esta função recebe 2interadores que representam o início e o final do vetor com os dados, devolvendo ao final de seu processamento um vetor com o volume para cada observação.

Debugando

A execução de um programa no modo de debug é iniciada com o programa setado em Debug, na opção de menu BUILD->SET ACTIVE CONFIGURATION e WIN32 Debug. A figura abaixo aponta o diálogo onde é possível setar o programa para ser debugado. A versão de lançamento não inclui no seu executável as informações necessárias para debug, portanto será menor e mais rápida.

Selecionando opção de debug

Figura 2: Selecionando opção de debug

Para iniciar a debugação deve-se selecionar a opção de menu BUILD->START DEBUG->GO ou simplesmente a tecla F5. A execução do programa irá prosseguir até encontrar um "breakpoint", ou ponto de parada. Para inserir um breakpoint, preferencialmente antes do programa já estar em execução, clique com o botão esquerdo do mouse na linha de código alvo. Será exibido um diálogo como o abaixo:

Menu de opções de debug

Figura 3:Menu de opções de debug

Ao selecionar em "Insert/Remove Breakpoint", será criada à esquerda da linha de código um círculo vermelho que indica um breakpoint ativo. Veja abaixo:

Breakpoint inserido

Figura 4: Breakpoint inserido

Para prosseguir a execução, após o breakpoint, podem ser usadas as teclas: a) Execução linha à linha: pressione F10 b) Execução até o próximo breakpoint: F5

No arquivo de projeto, foram criados breakpoints na funções dos 3 arquivos, para acompanhar a execução.

Examinando o conteúdo das variáveis

Após iniciar a execução do programa, este deverá pausar na linha marcada da última figura, presente no arquivo principal de programa. Neste momento, esperamos já ter aberto 2 arquivos, bem como 2 objetos STL (StandartTemplate Library) para conter os dados de entrada e saída.

Na porção inferior da janela onde se examina o código fonte, se encontra a área onde é possível examinar as variáveis e seus valores. Existem 4 "tabpages" chamadas de "WatchN", onde a numeração vai de 1 a 4. Elas permitem examinar as variáveis de diferentes partes do programa, pois existem variáveis que são locais a uma função e não visíveis a outras.

Analisando variáveis

Figura 5: Analisando variáveis

Para verificar se os arquivos foram corretamente abertos, no campo "NAME" da área de exploração de dados (AED, digitaremos os nomes de cada manipulador de arquivo criado (respectivamente fin e fout). Após digitar ENTER, a AED exibirá um símbolo de "+" ao lado de cada nome, indicando que estes objetos têm membros internos com dados. Basta clicar no nome para visualizar o interior dos dados.

Ao clicar F10, a mensagem será exibida e o cursor de execução apontará para a próxima linha, que chama a função que carrega o arquivo. Clicando F10 novamente, será visualizado o código abaixo:

Valor das variáveis analisadas

Figura 6: Valor das variáveis analisadas

Deve-se observar que as variáveis de manipulação de arquivos foram definidas na função principal do programa, por isso, o valor das mesmas não pode ser visualizado a partir deste ponto onde o programa está executando. Para examinar o conteúdo das variáveis deste módulo, iremos utilizar outro "Watch" para manter a organização durante o processo de debug, embora seja possível continuar na tabpage atual.

Digite F10 para avançar na execução e logo a seguir o nome da estrutura temporária no AED. Veremos que ela possui valores espúrios, ao examinarmos o seu interior, como abaixo:

Valores das variáveis antes do avanço do código

Figura 7: Valores das variáveis antes do avanço do código

Ao clicarmos 2X a tecla F10, os valores da primeira linha do arquivo serão lidos, e os valores dos campos da estrutura mudarão:

Valores das variáveis após vanço do código

Figura 8: Valores das variáveis após avanço do código

É possível constatar que foi possível abrir o arquivo e ler a primeira linha, carregando os dados para a instância Temp da estrutura DATA. Esta estrutura será copiada para dentro do vetor e o processo prosseguirá até o final do arquivo.

Como já constatamos que as coisas estão indo bem, vamos desligar o breakpoint setado no WHILE e já passar para o final da função. Para isso, deve-se clicar como o botão esquerdo do mouse na linha de código do WHILE e escolher a opção DISABLE BREAKPOINT presente no diálogo padrão. O ponto passará a cor negra. Ao clicar F5, o programa executará até o próximo breakpoint, o que fica no final da função, como abaixo:

Próximo breakpoint

Figura 9:Próximo breakpoint

Note que como ainda estamos na função, o último valor do arquivo ainda é visível na estrutura TEMP. Ao pressionar F10 novamente, deve-se voltar à função principal do programa. No entanto, como desejamos ir direto para a próxima função, ao pressionar F5, o programa deverá seguir para a função "Calcvol". Veja abaixo:

Continuando a execução, o programa irá calcular o volume para cada observação e salvar o conteúdo do vetor retornado pela função Calcvol em um arquivo de saída. Apenas para referência, os valores utilizados foram:

Tabela 1: Valores utilizados para o calculo

DAP Altura Volume
20.3 7 0.527174
54.6 12 0.695657
40.7 8 0.060903
73.2 15 0.761088

Conclusão

Neste tutorial foi apresentado um programa para demonstrar as principais funções básicas do debugador do Visual C++ 6.0. Foram descritos os procedimentos necessários para criar e desativar breakpoints, executar o programa linha-a-linha e a cada breakpoint, bem como visualizar o conteúdo de variáveis/estruturas e classes através do AED.

Estas são as habilidades mínimas para debugar programas de maneira fácil e eficiente, e acredita-se que ao final do tutorial o leitor tenha adquirido conhecimento para utilizar este debugador de maneira adequada. Um tópico que não foi coberto é a questão de alteração de valores de variáveis em tempo de execução para testes de robustez de algoritmos, embora esta seja uma questão a ser abordada em um futuro tutorial.

Junto com o arquivo zipado encontra-se os arquivos de projeto e fontes do programa analisado, bem como o arquivo de entrada de dados com as observações de diâmetro e altura. Como recomendação final, sugiro que os fontes sejam extraídospara uma pasta chamada "Debugtutor" localizado no drive "C:" para não ser necessário mudar os paths do comandos de inclusão dos arquivos no código fonte.

Baixe os arquivos necessários:

Adenilson Cavalcanti da Silva

Adenilson Cavalcanti da Silva - Adenilson (a.k.a. Savago) desenvolve sistemas há 10 anos, utilizando diversas linguagens de programação e sistemas operacionais. Tendo se especializado em C++, está sempre a procura de novos desafios com características multidisciplinares. Mestre pela USP, possui interesse especial por visão artificial, *nix, programação baixo nível.