print the segmentation fault reason [duplicate] print the segmentation fault reason [duplicate] unix unix

print the segmentation fault reason [duplicate]


If you want to know the cause you can register a signal handler, something like:

void handler(int signum, siginfo_t *info, void *context){  struct sigaction action = {    .sa_handler = SIG_DFL,    .sa_sigaction = NULL,    .sa_mask = 0,    .sa_flags = 0,    .sa_restorer = NULL  };  fprintf(stderr, "Fault address: %p\n", info->si_addr);  switch (info->si_code) {  case SEGV_MAPERR:    fprintf(stderr, "Address not mapped.\n");    break;  case SEGV_ACCERR:    fprintf(stderr, "Access to this address is not allowed.\n");    break;  default:    fprintf(stderr, "Unknown reason.\n");    break;  }  /* unregister and let the default action occur */  sigaction(SIGSEGV, &action, NULL);}

And then somewhere you need to register it:

  struct sigaction action = {    .sa_handler = NULL,    .sa_sigaction = handler,    .sa_mask = 0,    .sa_flags = SA_SIGINFO,    .sa_restorer = NULL  };  if (sigaction(SIGSEGV, &action, NULL) < 0) {    perror("sigaction");  }

Basically you register a signal that fires when SIGSEGV is delivered, and you get some additional info, to quote the man page:

   The following values can be placed in si_code for a SIGSEGV signal:       SEGV_MAPERR    address not mapped to object       SEGV_ACCERR    invalid permissions for mapped object

These map to the two basic reasons for getting a seg fault -- either the page you accessed wasn't mapped at all, or you weren't allowed to perform whatever operation you attempted to that page.

Here after the signal handler fires it unregisters itself and replaces the default action. This causes the operation that failed to be performed again so it can be caught by the normal route. This is the normal behavior of a page fault (the precursor to getting a seg fault) so that things like demand paging work.


As already answered here: How to generate a stacktrace when my gcc C++ app crashes

You can (in the case of GCC with Linux/BSD at least) do this fairly easy:

Example code:

#include <stdio.h>#include <execinfo.h>#include <signal.h>#include <stdlib.h>void handler(int sig) {  void *array[10];  size_t size;  // get void*'s for all entries on the stack  size = backtrace(array, 10);  // print out all the frames to stderr  fprintf(stderr, "Error: signal %d:\n", sig);  backtrace_symbols_fd(array, size, 2);  exit(1);}int main(int argc, char **argv) {  signal(SIGSEGV, handler);   // install our handler  char * ptr = NULL;  *ptr = "hello"; /* this will cause a segmentation fault */}

Example output:

# gcc -g -rdynamic -o test test.c# ./testError: signal 11:0   test                                0x000000010e99dcfa handler + 421   libsystem_c.dylib                   0x00007fff95c1194a _sigtramp + 262   ???                                 0x0000000000000000 0x0 + 03   libdyld.dylib                       0x00007fff8fa177e1 start + 04   ???                                 0x0000000000000001 0x0 + 1