Seja Elegante
Talvez possa ser algo que passe despercebido por vários desenvolvedores, porém dúvido quem nunca tenha se deparado com mensagens de “log” vagas ou sem nenhum nexo ou bem pior, como mensagens idênticas replicadas por várias partes do código!
A algum tempo atrás estava trabalhando em um projeto em que um respectivo desenvolvedor da equipe possuia o costume de espalhar ou replicar centenas de printf() pelo código com mensagens tipo!
printf(“!!! FULANO – Aqui!!!”);
ou
printf(“!!! FULANO – Arquivo.cpp: Aqui!!!\n”);
Precisa falar que isto e pessímo? Certo que e preciso um bom senso com o uso de mensagens de depuração pois dependendo ao invés de ajudar podem só atrapalhar. principalmente quando você necessita ter controle sobre tais mensagens, como por exemplo obter a localização da mensagem através do nome da função, arquivo e linha.
O pré-processador do GCC oferece (*) várias macros, as que irei utilizar em questão são:
- __FILE__ : Substituída pelo nome do arquivo.
- __PRETTY_FUNCTION__ : Substituídas pelo nome nome da função.
- __LINE__ : Substituída pelo número da linha de código.
(*) Mais detalhes sobre as macros do GCC.
A utilização dessas macros irá facilitar a localização das mensagens de depuração, Abaixo um simples exemplo demonstrado em debug1.c.
/** * By Jorge Pereira <jpereiran@gmail.com> * Date: Tue Jun 29 02:51:44 BRT 2010 */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> // Macro condicional #ifdef DEBUG # warning "Debug is enabled" # define TRACE_DEBUG(fmt, ...) \ fprintf(stderr, " ** DEBUG: %s:%d %s(): "fmt"\n", \ __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) #else # warning "Debug is disabled" # define TRACE_DEBUG(fmt, ...) #endif #define MAX_STRING 5 /* tamanho maximo de uma string */ // Função simples de exemplo... void show_name (const char* name, size_t len) { size_t offset = len; // Verificação qualquer... if (len > MAX_STRING) { // Abaixo mensagem de depuração, perceba que ela será ativada apenas // quando em tempo de compilação você ativar a macro "DEBUG" TRACE_DEBUG ("Ooops! Tamanho da string(%d) e excedeu o limite(%d)...", len, MAX_STRING); offset = MAX_STRING; } // Manipulação qualquer... write (STDOUT_FILENO, name, offset); write (STDOUT_FILENO, "\n", 1); } int main (int argc, char* argv[]) { if (argc < 2) { printf ("Usage: %s <string>\n", argv[0]); exit (1); } show_name (argv[1], strlen (argv[1])); return 0; }
Com este exemplo básico em mãos, vamos compilar e executar.
[jpereira@miracleworld Codes]$ gcc -Wall -o debug1 debug1.c debug1.c:18:3: warning: #warning "Debug is disabled" [jpereira@miracleworld Codes]$ ./debug1 "Jorge" Jorge [jpereira@miracleworld Codes]$ ./debug1 "Jorge Pereira" Jorge [jpereira@miracleworld Codes]$
Imagine que seu sistema possui inúmeros arquivos e você precisa em determinados pontos obter o máximo de informação sobre as mensagens de depuração, talvez seja interessante ter além de uma mensagem objetiva obter juntamente o nome da função, arquivo e linha de onde foi invocada tal mensagem.
[jpereira@miracleworld Codes]$ gcc -Wall -DDEBUG -o debug1 debug1.c debug1.c:13:3: warning: #warning "Debug is enabled" [jpereira@miracleworld Codes]$ ./debug1 "Jorge" Jorge [jpereira@miracleworld Codes]$ ./debug1 "Jorge Pereira" ** DEBUG: debug1.c:36 show_name(): Ooops! Tamanho da string(13) e excedeu o limite(5)... Jorge [jpereira@miracleworld Codes]$
Sem falar que torna-se um atrativo a possibilidade de você poder ativar/desativar o simples mecanismo, como por exemplo poder criar macros para depuração de componentes específicos (ex.: relacionadas a sockets, I/O, sgdb, …), isto poderá facilitar a identificação e remoção de bugs.
Dúvidas e Sugestões, são sempre bem vindas!
Autor: Jorge Pereira
0sem comentários ainda