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.
backtrace
function. But I really recommend you to run your program in a debugger instead, it will allow you to not only see the backtrace, but walk up the call-stack and examine variables.gdb
and the correct executable. This will give you the chance to see what exactly happened (unless the memory is not messed up, but that's pretty rare case) - see any variables' values, backtrace, threads, etc (of course, it would be nice to have max debug level and no optimizations for this type of investigation)*ptr
ischar
, but"hello"
's type ischar*
. you should probably assign a character (*ptr = 'h';
) or use amemmove()
or similar for the example to be correct. as it is, it takes the address of the string constant, casts it to integer, shaves it down to 1 byte, and then segfaults assigning it to*ptr