Cpp debug

From campisano.org
Jump to navigation Jump to search

Il programma DDD é un'alternativa decente a gdb senza perderne funzionalità utili e simili a quelle disponibili nel debugger di VisualStudio. Il problema é che cose come divisione per zero non generano exceptions in Linux, ma segnali che possono essere catturati con strumenti più 'antichi' e che non garantiscono che il programma continui normalmente.

Il problema fondamentale non é la divisione per zero, ma che un programmatore non ha testato questa eventualità e scelto cosa fare (in questo caso ha perfettamente senso che il programma non continui!). In queste situazioni è necessario che il programma segnali il problema prima di terminare, in questo modo il programmatore potrá individuare e correggere il problema.

Quello che si potrebbe fare è generare un dump della memoria e analizzarlo. In Linux è semplice ottenere il dump, è necessario indicare

ulimit -c unlimited 

prima di eseguire il programma.

Per Windows dovrebbe esserci uno strumento simile. Quello che segue é un estratto di una discussione su Usenet:

On Nov 6, 10:44 am, t1t0 <t...@noemail.not> wrote:
> On Sun, 06 Nov 2011 01:15:05 +0000, Kaz Kylheku wrote:

> > You can catch an exception (in every thread) and then use the API to
> > list the modules, snapshot the thread state and such.
>
> But what about signal error (like zero division)? Did Windows produce a
> signal error or a exception for this kind of error?

yes divide by zero generates on exception on Windows. There are ways
to turn this into text.

> > I wrote a crash dump reporter on Windows CE quite a few years ago.  It
> > was very helpful, because crashing programs would just "disappear
> > without a trace" on that platform
>
> Nice, this is exactly what I want to avoid at all costs: the death of the
> application without trace!
> So, on Windows there is an API to create a core dump, or is it a 'manual'
> implementation ?

search MSDN. I found MiniDumpWriteDump(),though my experience of
Windows minidumps is that they're a bit too limited.

From http://www.codeproject.com/Articles/6230/Auto-Memory-Dump-on-Crash-of-an-Application

We can make a debugger automatically pop up whenever an application crashes. This type of debugger
is called a post mortem or JIT Debugger and they can also automatically generate a crash memory dump
[...]
To set WinDbg to automatically generate a memory dump file when a program crashes, it is necessary
to edit the registry. On an x86 computer, the postmortem settings are stored in the
\\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug key.

Sembra sia possibile automatizzare il processo di creazione del dump:


Una soluzione quasi ideale sarebbe creare un Guardian, ovvero un programma minimale (confidabile, che non abbia errori) che preparerebbe l'ambiente e inizierebbe l'applicazione e in caso di crash invierebbe un email con il crashdump e reinizierebbe l'applicazione di nuovo.

Resta il fatto che per ottenere informazioni utili dal coredump, il programma dovrebbe essere compilato con le informazioni di debug, cosa che permetterebbe di ottenerne il codice sorgente. Una soluzione in Linux é compilare con le informazioni di debug e usare in produzione una copia 'pulita' con il comando strip:

from http://stackoverflow.com/questions/2251391/core-dump-in-linux

The usual solution is to build with -g and to strip off the debug information before releasing the file.
Look for the 'strip' command. You keep the file with debug information and use it to debug core dumps you get from customers.

from http://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html

gdb allows you to put a program's debugging information in a file separate from the executable itself,
in a way that allows gdb to find and load the debugging information automatically.
[...]
The gnu binary utilities (Binutils) package includes the `objcopy' utility that can produce
the separated executable / debugging information file pairs using the following commands:
     objcopy --only-keep-debug foo foo.debug
     strip -g foo

GDB

gcc -g -O0 src/main.c -o ./main           # compile with debug info and without optimization
ulimit -c unlimited                       # enable core dump
objdump --syms ./main | less              # test debug symbols existance
./main                                    # run the program with a fatal error, producing a core archive e.g. core.27133
gdb -tui ./main -c ./core.27133 -d ./src  # run the debuger
bt full                                   # see the full callstack

For more GDB commands, see GDB quick reference card, version 5.

  • from

- http://stackoverflow.com/a/22711917

- http://stackoverflow.com/a/22711917

- http://sourceware.org/gdb/current/onlinedocs/gdb/TUI.html

libSegFault.so

from http://groleo.wordpress.com/2010/05/04/when-you-cant-use-gdb-or-valgrind-there-is-liblibsegfault-so/

Under certain conditions I can’t get gdb or valgrind to work on my binary and I don’t want
any delays from them. And I just wanted to see where the binary segfaulted so I remembered of
/lib/libSegFault.so.


LD_PRELOAD=/lib/libSegFault.so executable
Backtrace:
/lib/libSegFault.so(+0x206f)[0x11206f]
[0x9d1400]
executable[0x805994d]
executable[0x8059a0d]
executable[0x805d043]
executable[0x8057d59]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xae5bd6]
executable[0x8048e81]

Now I use addr2line to translate the addresses to locations in binary:

addr2line -e executable 0x805994d 0x8059a0d 0x805d043 0x8057d59
sm.c:505
sm.c:564
tmr.c:104
main.c:155

Thats it .

For more details, see linux_LD_PRELOAD

Get human readable signal message

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

static void catch_function(int signal) {
    extern const char *const sys_siglist[];
    printf(
        "Interactive attention signal caught: '%d', message: '%s'\n",
        signal, sys_siglist[signal]
    );
}

int main(void) {
    if (signal(SIGINT, catch_function) == SIG_ERR) {
        fputs("An error occurred while setting a signal handler.\n", stderr);
        return EXIT_FAILURE;
    }
    puts("Raising the interactive attention signal.");
    if (raise(SIGINT) != 0) {
        fputs("Error raising the signal.\n", stderr);
        return EXIT_FAILURE;
    }
    puts("Exiting.");
    return 0;
}

See also

Profiling