1

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;
}
user438383
  • 5,716
  • 8
  • 28
  • 43
Nitesh
  • 131
  • 1
  • 16
  • 2
    `"random"` is a string literal and constant; it cannot be changed. Your various pointer varibales point to that immutable data array, so you get undefined behaviour when you try to change things in it. – Adrian Mole May 10 '20 at 18:59
  • See [here](https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s) (probable duplicate, though there may be better ones). – Adrian Mole May 10 '20 at 19:01
  • THEN WHY THIS IS WORKING ```char *p; *p = 'a'; printf("%c",*p);``` – Nitesh May 10 '20 at 19:16
  • 1
    Attempting to write to a `const` object is **undefined behaviour**. That means it can *appear* to work ... sometimes. – Adrian Mole May 10 '20 at 19:17
  • @Nitesh: Because you are lucky :) Nobody known where points uninitialized 'p'. – ZarathustrA May 10 '20 at 19:20
  • it happens with all the pointers ? – Nitesh May 10 '20 at 19:22
  • malloc assigns memory which is read write ..char *p = malloc (6); p = "hello"; p[0] = 'b'; *p = 'b';..not working – Nitesh May 10 '20 at 19:54

3 Answers3

3

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

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • char *p = malloc (6); p = "hello"; p[0] = 'b'; *p = 'b';..not working – Nitesh May 10 '20 at 19:53
  • 2
    @Nitesh It's the same problem! Your `p = "hello"` line ***replaces the address*** in `p` (given by `malloc`) with the address of the literal. Use `strcpy(p, "hello")` in that case. – Adrian Mole May 10 '20 at 19:55
  • thanks !.it is with all the literals or just string ? – Nitesh May 10 '20 at 20:01
  • @Nitesh String literals are the only common case where this 'confusion' happens. It is far more difficult to accidentally declare other array types as literal (or read-only). For instance, this line will not compile: `int* ip = { 1, 2, 3 };`. – Adrian Mole May 10 '20 at 20:07
  • its compiling ..but when try to print segfault...but print is read only function – Nitesh May 10 '20 at 20:15
  • What is compiling? But note, the segfault error can *appear* to come from strange code places, sometimes, depending on what tricks the compiler uses for optimization. – Adrian Mole May 10 '20 at 20:18
  • ohh yes ... u r right ...one last question ..This works `char *ch = "hi";` while this donot `int *arr = {1,3};` – Nitesh May 10 '20 at 20:27
  • This won't compiler either: `char* ch = { 'h', 'i', '\0' };`. String literals are a 'shorthand' way of declaring a **const** char array and returning a pointer to its first element. [cppreference](https://en.cppreference.com/w/cpp/language/string_literal). – Adrian Mole May 10 '20 at 20:32
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/213575/discussion-between-nitesh-and-adrian-mole). – Nitesh May 10 '20 at 20:54
1

"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.

ZarathustrA
  • 3,434
  • 32
  • 28
  • What you means by OP? – ZarathustrA May 10 '20 at 19:13
  • OP = original poster – marko May 10 '20 at 19:16
  • Not sure what you wanted to ask. However, the original post looks not changed to me. – ZarathustrA May 10 '20 at 19:21
  • why this gives segmentation fault :char *p = "random"; *p = 'N'; // ----> Segmentation fault – Nitesh May 10 '20 at 19:22
  • Once again. 1) From the C++ viewpoint "random" is a constant string literal. 2) When compiler generates code, it places this literal in the read-only segment in executable 3) When the OS loads your program, it reads and parses executable 4) OS see that there is Read-Only segment and allocates read-only memory region where content of this segment is placed 5) So, when you tries to write into this region, MMU, which is a part of CPU that controls access to the memory, detects that you are trying to do something wrong from the OS viewpoint -- you tries to write to Read-Only memory – ZarathustrA May 10 '20 at 19:23
  • 6) When MMU detects such a misbehavior of your program, it generates Page Fault Exception, which transfers control to the OS kernel, which than reports it to you as "General Protection Fault". – ZarathustrA May 10 '20 at 19:28
  • int arr[] = {1,2,3}; *arr = 3; is working ..here 1,2,3 is also constants ..why this is working ?? – Nitesh May 10 '20 at 19:28
  • "arr" is an array of integers which is not marked as constant. "random" is a string literal and is constant by default in C. – ZarathustrA May 10 '20 at 19:30
  • 1
    where the string literals are placed is 100% implementation dependant. You shuld not modify string literals because the STANDARD of the language does not alow it. For exampe avr-gcc places string literals in RAM and nothing will happen. But it is still Uan B – 0___________ May 10 '20 at 20:02
  • @P__J__ completely right answer. Standard claims that attempt to modify string literal is undefined behavior (UB) and thus completely implementation specific. That means that if programmer wants to write clean portable code then he should not introduce UB in the code. In the particular case of Nitesh, he got GPF because OS locates string literals in the protected memory region. However, another compiler and/or operating system can show another behavior. – ZarathustrA May 11 '20 at 11:09
0

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

0___________
  • 60,014
  • 4
  • 34
  • 74