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!";