C – Why Does This Program Throw a Segmentation Fault at Runtime?

arraysc++charpointersstring

I'm declaring character array as char* string. And then I declare other pointer which again refer to original string, then when I'm going to change any thing on that string, at runtime program throws segmentation fault.


#include <string.h>

#include <ctype.h>

int main(void)

{

char* s = "random";

char* t = s;

 *t = 'R'; // ----> Segmentation fault

 t[0] = toupper(t[0]); // ----> Segmentation fault

 *s = 'R'; // ----> Segmentation fault

 s[0] = 'R'; // ----> Segmentation fault

printf("s is : %s , address : %p \n", s,s);

printf("t is : %s , address : %p \n", t,t);

return 0;

}

even this is not working :

#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(void)
{
char *p = "random";
*p = 'N'; // ----> Segmentation fault

return 0;
}

Best Answer

I'm declaring character array as char* string.

This is where your problems begin! Although pointers and arrays have some things in common, syntactically, they are not the same. What you are doing in the line copied below is declaring s as a pointer to a char and initializing that pointer with the address of the string literal you provide.

char* s = "random";

As a string literal, the compiler is allowed to (though not obliged to) allocate memory for that data in read-only memory; thus, when you attempt (later) to modify the character pointed to by (the address in) the s variable (or any other pointer, such as your t, which contains the same address), you will experience undefined behaviour. Some systems will cause your program to crash ("Segmentation fault"), others may silently allow you to 'get away' with it. Indeed, you may even get different result with the same code at different times.

To fix this, and to properly declare a character array, use the [] notation:

char a[] = "random";

This will declare a as a (modifiable) array of characters (whose size is determined, in this case, by the initial value you give it - 7, here, with the terminating nul character included); then, the compiler will initialize that array with a copy of the string literal's data. You are then free to use an expression like *a to refer to the first element of that array.

The following short program may be helpful:

#include <stdio.h>
int main()
{
    char* s = "random";
    *s = 'R'; // Undefined behaviour: could be ignored, could crash, could work!
    printf("%s\n", s);
    char a[] = "random";
    *a = 'R'; // Well-defined behaviour - this will change the first letter of the string.
    printf("%s\n", a);
    return 0;
}

(You may need to comment-out the lines that use s to get the code to run to the other lines!)

Related Question