Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking debugger from within a C program

I am reading the book - "C Interfaces and Implementations" by David Hanson. This exercise questions seems interesting and am unable to find a solution:

On some systems, a program can invoke a debugger on itself when it has detected an error. This facility is particularly useful during development, when assertion failures may be common.

Can you provide a short example on how to invoke a debugger.

void handle_seg_fault(int arg)
{
    /* how to invoke debugger from within here */
}

int main()
{
    int *ptr = NULL;
    signal(SIGSEGV, handle_seg_fault);
    /* generate segmentation fault */
    *ptr = 1;
}
like image 639
user138645 Avatar asked Jul 16 '12 07:07

user138645


People also ask

Does C have debugger?

GCC is a compiler for C language that can be used to compile C code. It creates an executable after compiling that can be executed directly. GDB is a debugger that can debug code in many languages like C, C++, Objective-C, etc.

How do you run and debug C program in VS code?

To do that, open C++ file in VSCode and either hit F5 or go to Debug -> Start Debugging and select C++ (GDB/LLDB) then select g++.exe build and debug active file .

How do you go inside a function while debugging in Visual Studio?

In most languages supported by Visual Studio, you can edit your code in the middle of a debugging session and continue debugging. To use this feature, click into your code with your cursor while paused in the debugger, make edits, and press F5, F10, or F11 to continue debugging.


2 Answers

I have got this:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>

void exception_handler(int)
{
    int pid = getpid();
    if (fork() != 0) {
        while(true) sleep(1000);
    }
    char buf[20];
    sprintf(buf, "--pid=%u", pid);
    execlp("gdb", "gdb", buf, NULL);
    exit(-1);
}

int init()
{
    if (signal(SIGSEGV, exception_handler) < 0) {
       return errno;
    }
    if (signal(SIGILL, exception_handler) < 0) {
        return errno;
    }
    if (signal(SIGFPE, exception_handler) < 0) {
        return errno;
    }
    return 0;
}

int main()
{
    if (int rc = init()) {
       fprintf(stderr, "init error: %s\n", strerror(rc));
       return 1;
    }
    *((char*)(0)) = 1;
}
like image 45
Dmitry Poroh Avatar answered Oct 03 '22 18:10

Dmitry Poroh


Elaborating on Christian.K's comment, fork()ing a debugger in the face of something like a SIGFPE or SIGSEGV might not be the best of ideas, because...

  1. your program is potentially corrupt to begin with, making the fork() unsafe;
  2. you might want to use something different for debugging than what the program has hardcoded;
  3. the average application user does not know how to handle a debugger;
  4. anyone competent with a debugger will usually prefer the coredump over the auto-invoked debugger.

A coredump that I can copy to a testbed beats a debugger instance at my customer's workplace any time of the day. A debugger interface makes for a lousy end-user error message.

like image 143
DevSolar Avatar answered Oct 03 '22 19:10

DevSolar