Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

print the segmentation fault reason [duplicate]

Let's say I have a code that causes segmentation fault.

char * ptr = NULL;
*ptr = "hello"; /* this will cause a segmentation fault */

How do I print on runtime, the address in memory that the segmentation fault occurred at, and the reason for the segmentation fault (accessing to forbidden memory region, or something else).

I read about core dump files, but I'm not sure if it's the correct solution.

How can I do this?

P.S, I'm aware to do fact that I can achieve that by using gdb, or an other debugger, but the purpose is to do this by using code, and only code.

like image 921
Lior Avatar asked Apr 15 '13 12:04

Lior


People also ask

How do I find out what is causing my segmentation fault?

Use debuggers to diagnose segfaults Start your debugger with the command gdb core , and then use the backtrace command to see where the program was when it crashed. This simple trick will allow you to focus on that part of the code.

How do you fix a segmentation fault?

It can be resolved by having a base condition to return from the recursive function. A pointer must point to valid memory before accessing it.

What is segmentation fault with example?

A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system).

What causes a segmentation fault in Python?

Tip: A segmentation fault (also known as segfault) is a common condition that causes programs to crash; A segmentation fault is typically caused by a program trying to read from or write to an illegal memory location, that is, part of the memory to which the program is not supposed to have access.


2 Answers

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.

like image 164
FatalError Avatar answered Oct 19 '22 03:10

FatalError


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
# ./test
Error: signal 11:
0   test                                0x000000010e99dcfa handler + 42
1   libsystem_c.dylib                   0x00007fff95c1194a _sigtramp + 26
2   ???                                 0x0000000000000000 0x0 + 0
3   libdyld.dylib                       0x00007fff8fa177e1 start + 0
4   ???                                 0x0000000000000001 0x0 + 1
like image 42
Wolph Avatar answered Oct 19 '22 02:10

Wolph