Entradas para melhorar a depuração do código além dos registros e códigos de erro

StackOverflow https://stackoverflow.com/questions/2177597

  •  24-09-2019
  •  | 
  •  

Pergunta

Além dos códigos de erro, strings de erro e logs, existem outros recursos que podem ser incorporados no código para aumentar a obtenção de informações de depuração / rastreamento durante o tempo de execução do código que podem ajudar a depurar problemas (ou informar o que está acontecendo) no tempo de execução?

Foi útil?

Solução

Aqui está um exemplo do código que envia uma pilha para um arquivo após uma falha de segmentação

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>

static void signal_handler(int);
static void dumpstack(void);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);

struct sigaction sigact;
char *progname;

int main(int argc, char **argv){
    char *s;
    progname = *(argv);
    atexit(cleanup);
    init_signals();
    printf("About to seg fault by assigning zero to *s\n");
    *s = 0;
    sigemptyset(&sigact.sa_mask);
    return 0;
}

void init_signals(void){
    sigact.sa_handler = signal_handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGSEGV);
    sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGBUS);
    sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGQUIT);
    sigaction(SIGQUIT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGHUP);
    sigaction(SIGHUP, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGKILL);
    sigaction(SIGKILL, &sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig){
    if (sig == SIGHUP) panic("FATAL: Program hanged up\n");
    if (sig == SIGSEGV || sig == SIGBUS){
        dumpstack();
        panic("FATAL: %s Fault. Logged StackTrace\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
    }
    if (sig == SIGQUIT) panic("QUIT signal ended program\n");
    if (sig == SIGKILL) panic("KILL signal ended program\n");
    if (sig == SIGINT) ;
}

void panic(const char *fmt, ...){
    char buf[50];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, buf);
    exit(-1);
}

static void dumpstack(void){
    /* Got this routine from http://www.whitefang.com/unix/faq_toc.html
    ** Section 6.5. Modified to redirect to file to prevent clutter
    */
    char dbx[160];
    sprintf(dbx, "echo 'where\ndetach' | dbx -a %d > %s.dump", getpid(), progname);
    system(dbx);
    return;
}

void cleanup(void){
    sigemptyset(&sigact.sa_mask);
    /* Do any cleaning up chores here */
}

Na função dumpstack, dbx precisa ser alterado para se adequar ao seu depurador, como gdb Para o depurador da GNU, esse código foi usado quando eu estava programando na caixa AIX há alguns anos. Observe como os sinais são configurados e, se ocorrer uma falha Sigsegv, o manipulador despeja a pilha em um arquivo com extensão .dump. O código demonstra a falha de segmentação e despeja o Stacktrace.

Esse é o meu código favorito.

Espero que isso ajude, cumprimentos, Tom.

Outras dicas

  • Construir sem otimização, para preservar o máximo possível da "intenção" do código
  • Construir no modo de depuração, para adicionar informações de símbolo
  • Não retire o executável (em sistemas Linux/Unix), para manter o máximo de informações do símbolo possível para os depuradores usarem

Ao construir o Linux, eu gosto de poder imprimir um empilhe backtrace de um manipulador de sinal. Isso ajuda a depurar falhas (SIGSEGV) ou me permite enviar um sinal ao programa para iniciar um backtrace da pilha em tempo de execução. Dumps centrais Também pode ser útil na depuração de depuração (novamente no Linux).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top