Why this C program throws segmentation fault at runtime?

梦想的初衷 提交于 2021-02-05 09:11:38

问题


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;
}

回答1:


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!)




回答2:


"random" is a constant string literal. It is placed by OS into the protected Read-Only Memory (CPU is instructed by OS to prevent write operations in this memory). 's' and 't' both point to this protected read-only memory region. Once you tries to write into it, CPU detects this attempt and generates exception.




回答3:


you try to modify the string literal. It is an Undefined Behavoiur and everything may happen including the segfault.

from the C standard what is an UB:

—The program attempts to modify a string literal (6.4.5).



来源:https://stackoverflow.com/questions/61717229/why-this-c-program-throws-segmentation-fault-at-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!