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