What is the reason for SIGSEGV Bad permissions for mapped region at address ...

Short explanation

Ensure the value the pointer is pointing to is not in non-modifiable memory.

/* Reserves local storage for the array just like any other mutable variable
 * initialises it to the value of the string literal.
 */
char arr[] = “literal”;

/* Reserves local storage for the pointer and initialises it to point at 
 * the address of the string literal within the executable image in memory. 
 * This address is usually in a non-modifiable page.
 */
char ptr* = “literal”;

Long Explanation


This is mostly based on a post at http://panicsoftware.co.uk/index.php/Valgrind:_Bad_permissions_for_mapped_region_at_address_...

Solution: Declare string parameter as char s[] = "1234567"; not char* s = "12345";

This error is very hard to spot when using a C (as opposed to C++) compiler. On the face of it, it can appear that perfectly fine code produces a random segfault that seems to have no good reason for happening. Segfaults are the arch enemy of any C programmer, and usually indicate feeble, insignificant human error; and, like this case, it is often true.

Take the following simple code:

void changeLetter(char* theWord)
{
   if (theWord)
      theWord[0] = 'H';
}
I pass this method the char string "hello!", which should change the 'h' at the start of the string to 'H', and it produces a segfault. Why? I've passed it a valid pointer-to-char string, otherwise the IF statement would have failed. When running using GDB, I can see the following:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400480 in changeLetter ()

Not very descriptive. Compiling the program giving extra debugging symbols using -g3:

gcc -g3 -o problem problem.c

This enables debuggers to give us more meaningful output than what we have already have. GDB now tells us:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400487 in changeLetter (theWord=0x4005a8 "hello!") at problem.c:4
4           theWord[0] = 'H';

We can see that we are passing a non-null pointer, but we still have a problem. In this situation, unfortunately, it means we have defined the char string incorrectly. If you saw my main method, you'd see:

int main()
{
   char* hello = "hello!";

   changeLetter(hello);

   return 0;
}

Unfortunately, the C standard says that this use will result in undefined behaviour. This is where valgrind comes in useful, because it can give more useful feedback than GDB. Valgrind says:
==4927== Process terminating with default action of signal 11 (SIGSEGV)
==4927==  Bad permissions for mapped region at address 0x4005A8
==4927==    at 0x400487: changeLetter (ro_mem.c:4)
==4927==    by 0x4004A7: main (ro_mem.c:10)

If we wish to modify the string we created, we need to declare it like so:

/* 
 * Reserves local storage for the array just like any other mutable variable
 * initialises it to the value of the string literal.
 */
char hello[] = "hello!";