Why Segmentation fault in following code? - c

I read this on wikipedia
int main(void)
{
char *s = "hello world";
*s = 'H';
}
When the program containing this code is compiled, the string "hello world" is placed in the section of the program executable file marked as read-only; when loaded, the operating system places it with other strings and constant data in a read-only segment of memory. When executed, a variable, s, is set to point to the string's location, and an attempt is made to write an H character through the variable into the memory, causing a segmentation fault**
i don't know why the string is placed in read only segment.please someone could explain this.

String literals are stored in read-only memory, that's just how it works. Your code uses a pointer initialized to point at the memory where a string literal is stored, and thus you can't validly modify that memory.
To get a string in modifiable memory, do this:
char s[] = "hello world";
then you're fine, since now you're just using the constant string to initialize a non-constant array.

There is a big difference between:
char * s = "Hello world";
and
char s[] = "Hello world";
In the first case, s is a pointer to something that you can't change. It's stored in read-only memory (typically, in the code section of your application).
In the latter case, you allocate an array in read-write memory (typically plain RAM), that you can modify.

When you do: char *s = "hello world"; then s is a pointer that points to a memory that is in the code part, so you can't change it.
When you do: char s[] = "Hello World"; then s is an array of chars
that are on the stack, so you can change it.
If you don't want the string to be changed during the program, it is better to do: char
const *s = ....;. Then, when you try to change the string, your program will not crash with segmentation fault, it will arise a compiler error (which is much better).

first have a good understanding of pointers, I will give u a short demo:
First let us analyze your code line by line. Lets start from main onwards
char *s = "Some_string";
first of all, you are declaring a pointer to a char variable, now *s is a address in memory, and C will kick you if you try to change its memory value, thats illegal, so u better declare a character array, then assign s to its address, then change s.
Hope you get, it. For further reference and detailed understanding, refer KN King: C programming A Modern Approach

Per the language definition, string literals have to be stored in such a way that their lifetime extends over the lifetime of the program, and that they are visible over the entire program.
Exactly what this means in terms of where the string gets stored is up to the implementation; the language definition does not mandate that string literals are stored in read-only memory, and not all implementations do so. It only says that attempting to modify the contents of a string literal results in undefined behavior, meaning the implementation is free to do whatever it wants.

Related

How char * pointers works [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 5 years ago.
I am trying to write code to reverse a string in place (I'm just trying to get better at C programming and pointer manipulation), but I cannot figure out why I am getting a segmentation fault:
#include <string.h>
void reverse(char *s);
int main() {
char* s = "teststring";
reverse(s);
return 0;
}
void reverse(char *s) {
int i, j;
char temp;
for (i=0,j = (strlen(s)-1); i < j; i++, j--) {
temp = *(s+i); //line 1
*(s+i) = *(s+j); //line 2
*(s+j) = temp; //line 3
}
}
It's lines 2 and 3 that are causing the segmentation fault. I understand that there may be better ways to do this, but I am interested in finding out what specifically in my code is causing the segmentation fault.
Update: I have included the calling function as requested.
There's no way to say from just that code. Most likely, you are passing in a pointer that points to invalid memory, non-modifiable memory or some other kind of memory that just can't be processed the way you process it here.
How do you call your function?
Added: You are passing in a pointer to a string literal. String literals are non-modifiable. You can't reverse a string literal.
Pass in a pointer to a modifiable string instead
char s[] = "teststring";
reverse(s);
This has been explained to death here already. "teststring" is a string literal. The string literal itself is a non-modifiable object. In practice compilers might (and will) put it in read-only memory. When you initialize a pointer like that
char *s = "teststring";
the pointer points directly at the beginning of the string literal. Any attempts to modify what s is pointing to are deemed to fail in general case. You can read it, but you can't write into it. For this reason it is highly recommended to point to string literals with pointer-to-const variables only
const char *s = "teststring";
But when you declare your s as
char s[] = "teststring";
you get a completely independent array s located in ordinary modifiable memory, which is just initialized with string literal. This means that that independent modifiable array s will get its initial value copied from the string literal. After that your s array and the string literal continue to exist as completely independent objects. The literal is still non-modifiable, while your s array is modifiable.
Basically, the latter declaration is functionally equivalent to
char s[11];
strcpy(s, "teststring");
You code could be segfaulting for a number of reasons. Here are the ones that come to mind
s is NULL
s points to a const string which is held in read only memory
s is not NULL terminated
I think #2 is the most likely. Can you show us the call site of reverse?
EDIT
Based on your sample #2 is definitely the answer. A string literal in C/C++ is not modifiable. The proper type is actually const char* and not char*. What you need to do is pass a modifiable string into that buffer.
Quick example:
char* pStr = strdup("foobar");
reverse(pStr);
free(pStr);
Are you testing this something like this?
int main() {
char * str = "foobar";
reverse(str);
printf("%s\n", str);
}
This makes str a string literal and you probably won't be able to edit it (segfaults for me). If you define char * str = strdup(foobar) it should work fine (does for me).
Your declaration is completely wrong:
char* s = "teststring";
"teststring" is stored in the code segment, which is read-only, like code. And, s is a pointer to "teststring", at the same time, you're trying to change the value of a read-only memory range. Thus, segmentation fault.
But with:
char s[] = "teststring";
s is initialized with "teststring", which of course is in the code segment, but there is an additional copy operation going on, to the stack in this case.
See Question 1.32 in the C FAQ list:
What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value to p[i].
Answer:
A string literal (the formal term for a double-quoted string in C source) can be used in two slightly different ways:
As the initializer for an array of char, as in the declaration of char a[], it specifies the initial values of the characters in that array (and, if necessary, its size).
Anywhere else, it turns into an unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, as usual (see section 6), so the second declaration initializes p to point to the unnamed array's first element.
Some compilers have a switch controlling whether string literals are writable or not (for compiling old code), and some may have options to cause string literals to be formally treated as arrays of const char (for better error catching).
(emphasis mine)
See also Back to Basics by Joel.
Which compiler and debugger are you using? Using gcc and gdb, I would compile the code with -g flag and then run it in gdb. When it segfaults, I would just do a backtrace (bt command in gdb) and see which is the offending line causing the problem. Additionally, I would just run the code step by step, while "watching" the pointer values in gdb and know where exactly is the problem.
Good luck.
As some of the answers provided above, the string memory is read-only. However, some compilers provide an option to compile with writable strings. E.g. with gcc, 3.x versions supported -fwritable-strings but newer versions don't.
I think strlen can not work since s is not NULL terminated. So the behaviour of your for iteration is not the one you expect.
Since the result of strlen will be superior than s length you will write in memory where you should not be.
In addition s points to a constant strings hold by a read only memory. You can not modify it. Try to init s by using the gets function as it is done in the strlen example

constant pointer and pointer to constant in a string [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 5 years ago.
I am trying to write code to reverse a string in place (I'm just trying to get better at C programming and pointer manipulation), but I cannot figure out why I am getting a segmentation fault:
#include <string.h>
void reverse(char *s);
int main() {
char* s = "teststring";
reverse(s);
return 0;
}
void reverse(char *s) {
int i, j;
char temp;
for (i=0,j = (strlen(s)-1); i < j; i++, j--) {
temp = *(s+i); //line 1
*(s+i) = *(s+j); //line 2
*(s+j) = temp; //line 3
}
}
It's lines 2 and 3 that are causing the segmentation fault. I understand that there may be better ways to do this, but I am interested in finding out what specifically in my code is causing the segmentation fault.
Update: I have included the calling function as requested.
There's no way to say from just that code. Most likely, you are passing in a pointer that points to invalid memory, non-modifiable memory or some other kind of memory that just can't be processed the way you process it here.
How do you call your function?
Added: You are passing in a pointer to a string literal. String literals are non-modifiable. You can't reverse a string literal.
Pass in a pointer to a modifiable string instead
char s[] = "teststring";
reverse(s);
This has been explained to death here already. "teststring" is a string literal. The string literal itself is a non-modifiable object. In practice compilers might (and will) put it in read-only memory. When you initialize a pointer like that
char *s = "teststring";
the pointer points directly at the beginning of the string literal. Any attempts to modify what s is pointing to are deemed to fail in general case. You can read it, but you can't write into it. For this reason it is highly recommended to point to string literals with pointer-to-const variables only
const char *s = "teststring";
But when you declare your s as
char s[] = "teststring";
you get a completely independent array s located in ordinary modifiable memory, which is just initialized with string literal. This means that that independent modifiable array s will get its initial value copied from the string literal. After that your s array and the string literal continue to exist as completely independent objects. The literal is still non-modifiable, while your s array is modifiable.
Basically, the latter declaration is functionally equivalent to
char s[11];
strcpy(s, "teststring");
You code could be segfaulting for a number of reasons. Here are the ones that come to mind
s is NULL
s points to a const string which is held in read only memory
s is not NULL terminated
I think #2 is the most likely. Can you show us the call site of reverse?
EDIT
Based on your sample #2 is definitely the answer. A string literal in C/C++ is not modifiable. The proper type is actually const char* and not char*. What you need to do is pass a modifiable string into that buffer.
Quick example:
char* pStr = strdup("foobar");
reverse(pStr);
free(pStr);
Are you testing this something like this?
int main() {
char * str = "foobar";
reverse(str);
printf("%s\n", str);
}
This makes str a string literal and you probably won't be able to edit it (segfaults for me). If you define char * str = strdup(foobar) it should work fine (does for me).
Your declaration is completely wrong:
char* s = "teststring";
"teststring" is stored in the code segment, which is read-only, like code. And, s is a pointer to "teststring", at the same time, you're trying to change the value of a read-only memory range. Thus, segmentation fault.
But with:
char s[] = "teststring";
s is initialized with "teststring", which of course is in the code segment, but there is an additional copy operation going on, to the stack in this case.
See Question 1.32 in the C FAQ list:
What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value to p[i].
Answer:
A string literal (the formal term for a double-quoted string in C source) can be used in two slightly different ways:
As the initializer for an array of char, as in the declaration of char a[], it specifies the initial values of the characters in that array (and, if necessary, its size).
Anywhere else, it turns into an unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, as usual (see section 6), so the second declaration initializes p to point to the unnamed array's first element.
Some compilers have a switch controlling whether string literals are writable or not (for compiling old code), and some may have options to cause string literals to be formally treated as arrays of const char (for better error catching).
(emphasis mine)
See also Back to Basics by Joel.
Which compiler and debugger are you using? Using gcc and gdb, I would compile the code with -g flag and then run it in gdb. When it segfaults, I would just do a backtrace (bt command in gdb) and see which is the offending line causing the problem. Additionally, I would just run the code step by step, while "watching" the pointer values in gdb and know where exactly is the problem.
Good luck.
As some of the answers provided above, the string memory is read-only. However, some compilers provide an option to compile with writable strings. E.g. with gcc, 3.x versions supported -fwritable-strings but newer versions don't.
I think strlen can not work since s is not NULL terminated. So the behaviour of your for iteration is not the one you expect.
Since the result of strlen will be superior than s length you will write in memory where you should not be.
In addition s points to a constant strings hold by a read only memory. You can not modify it. Try to init s by using the gets function as it is done in the strlen example

Initializing a string in C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between char *str=“STRING” and char str[] = “STRING”?
I wrote the following code:
int main()
{
char *str = "hello";
str[0] = 'H';
printf("%s\n", str);
}
This gives me a segmentation fault, I cant understand why.
str is pointer to char not const char. Even if that's the case shouldn't it give a compile error like the following program:
int main()
{
const char *str = "hello";
str[0] = 'H';
printf("%s\n", str);
}
It gives an error: assignment of read-only location *str.
EDIT
If my code places the pointer to a read only location, shouldn't I get a compilation error?
You assign a pointer to a constant string (which comes as a part of your text and is thus not writable memory).
Fix with char str[] = "hello"; this will create a r/w copy of the constant string on your stack.
What you do is a perfectly valid pointer assignment. What the compiler does not know is that in a standard system constant strings are placed in read-only memory. On embedded (or other weird) systems this may be different.
Depending on your system you could come with an mprotect and change the VM flags on your pointer destination to writable. So the compiler allows for this code, your OS does not though.
When you initialize a char * using a literal string, then you shouldn't try to modify it's contents: the variable is pointing to memory that doesn't belong to you.
You can use:
char str[] = "hello";
str[0] = 'H';
With this code you've declared an array which is initialized with a copy of the literal string's contents, and now you can modify the array.
Your code has undefined behavior in runtime. You are attempting to write to a literal string, which is not allowed. Such writes may trigger an error or have undefined behavior. Your specific C compiler has str point to read-only memory, and attempting to write to that memory leads to a segmentation fault. Even though it's not const, the write is still not allowed.
char *str = "hello";
When you declare str as above, it is not guaranteed which part of memory it will be stored. str might be read-only depending on implementation. So trying to change it will cause segmentation fault.
In order to avoid segmentation faullt, declare str as an array of characters instead.
char *str = "hello";
here the string hello is a literal.
string literals are always stored in read only memory.
this is the reason you are getting a segmentation fault when you are trying to change the value at read only memory.
Declaring str as char* reserves memory for the pointer, but not for the string.
The compiler can put the memory for "hello" anywhere he likes.
You have no guarantee that str[i] is writable, so that's why in some compilers this results in a seg fault.
If you want to make sure that the string is in writable memory, then you have to allocate memory using alloc() or you can use
char str[] = "hello";

C string function (strcopy,strcat...,strstr) with arrays and pointers

Whenever I am using one of these functions in dev-C++(I know its old but for some reason still taught at my college.)
strcat,strcpy,strcmp,strchr...//And their variants stricmp...
The first argument for these functions always has to be an array (i.e:
char ch[]="hello";
But it can't be a pointer to a string bc for some reason this causes a crash.
In fact for an example look at both of these codes:
code1:
#include<stdio.h>
#include<string.h>
main()
{char ch[20]="Hello world!";
char *ch2="Hello Galaxy!";
strcat(ch,ch2);
printf("%s",ch);
scanf("%d")//Just to see the output.
}
This code works fine and gives the expected result(Hello World!Hello Galaxy!)
But the inverse code2 crashes.
code2:
#include<stdio.h>
#include<string.h>
main()
{char ch[20]="Hello world!";
char *ch2="Hello Galaxy!";
strcat(ch2,ch);
printf("%s",ch2);
scanf("%d")//Just to see the output.
}
This code crashes and causes a
file.exe has stopped working Error.
This is the same for almost all of the strings functions that takes two arguments.
What is the cause of this problem.
With char *ch2 = "Hello Galaxy!"; you are obtaining a pointer to a string literal. You should never attempt to modify a string literals, as this invokes undefined behaviour (which in your case has manifested as a crash).
With char ch[20] = "Hello World!"; you are initialising an array using the contents of a string literal, so you end up with your own modifiable copy of the string in ch.
Also, note that 20 characters is not enough for Hello World!Hello Galaxy! to fit, and this is also undefined behaviour, and known as overflowing your buffer.
char ch[20] = "Hello world!"
ch is an array of char initialized by the elements of a string literal (and the rest of the array is initialized with 0).
char *ch2="Hello Galaxy!";
ch2 is a pointer to a string literal.
String literals are not required to be modifiable in C. Modifying a string literal is undefined behavior in C.
There are two problems. The first is that your string literal is not long enough to hold the concatenated string "Hello world!Hello Galaxy!". The space allocated is only 13 bytes (12 characters plus the space for the '0' byte that terminates the string). The concatenated string requires 26 bytes (25 chars + 1 null-valued char).
However, this isn't the real problem. The real problem is that you're accessing memory that you should not be, and that the operating system often protects. Most implementations of C provide four areas of storage:
The stack, where variables you declare in a function are allocated
The heap, where calls to malloc/calloc/realloc allocate memory
Global static storage, where non-const global variables (those declared outside of a function) are allocated.
Global constant storage, where all string literals and other global variables declared const are allocated.
The first three areas are, in principle, modifiable. The fourth area is not, and is often stored in memory that the operating system marks as read-only. When you assign the string literal "Hello Galaxy!" tochar* ch2, the variablech2` points into global constant storage.
To give you a better idea, the following code generals a segfault when I run it:
#include <stdio.h>
int main(int argc, char** argv)
{
char* s = "Foo bar baz";
s[0] = 'B';
printf("%s\n",s);
return 0;
}
The segfault occurs in the s[0] = ... line, because I'm accessing storage that the operating system has marked as read-only.
That is about the size of pointer array..overflow problem..
char *ch2="Hello Galaxy!"; when you use this automaticly the size of *ch2 gets 14 with the null character but when you move the ch[] array into the *ch2 , you get an error. you cannot move an array with 20 size into another array with 14 size...
String literals are read-only.This means that if you assign:
char* str="Hello";
You can't pass str as first argument of strcpy and strcat, because this would cause to write over read-only memory.
If instead you declare it this way:
char str2[]="Hello";
Then the str2 array is stored on the stack, and you can change it's values.
You can still pass str to functions like strcmp (which just reads the wto strings and compare them), or as second argument of strcat and strcpy, since this doesn't cause the string to be written.
you got an error because you try to access the code section of your process which is read-only.
that is your string literal present in code and the address of that string literal you use in assignment to your pointer variable.
So you can access the code but you cannot modify this.
every executable file contain some sections
like...
1.text(code of your program as well as string literals present here)
2.data uninitialized
3.data initialized
you can veryfy this by command
size <executable-file-neme>
Also using command
objdump -D <executable-file-neme>

String Manipulation in C Question [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Why does simple C code receive segmentation fault?
Hey Everyone, I'm sure this is a very basic question, but apparently I'm not quite understanding something here.
I've been playing around with C a lot over winter break and just came across something that I thought would work but is giving me a segmentation fault.
if I declare a string as:
char name[5] = "Mike";
I can manipulate the string: *(name+1) = 'a'; This works fine, name becomes "Make".
If I declare as:
char *name = "Mike";
and then try the same thing: *(name+1) = 'a'; I get a segmentation fault. Why can't I do that?
If I malloc the space for the string: char *name = (char*)malloc(5*sizeof(char)); and then copy the string to name: strcpy(name,"Mike"); I can manipulate it like above just fine. *(name+1) = 'a'; works.
What is the difference between char *name = "Mike"', and char *name = (char*)malloc(5*sizeof(char)); strcpy(name,"Mike");? Aren't they both just pointing to memory containing the string?
Sorry for the noobish question!
char name[5] = "Mike" declares a local array and copies the string "Mike" into it. char* name = "Mike" assigns a pointer to "Mike" without copying. In both cases, "Mike" is a constant string held in a read-only page, and so in the second case you are trying to modify the original constant.
So far everybody has said it, but I'm not sure it's clear enough.
char array[5] = "Mike"
creates a constant string "Mike", allocates an array on the stack of size 5, and copies the constant string into it ( theoretically... the compiler will probably optimize a step out )
char *array = "Mike"
creates the same constant string "Mike", but then just assigns the pointer to it instead of copying it to the local stack.
By "constant string", it may be a string allocated in memory and marked read-only by the operating system, so your attempt to modify it causes the segmentation fault.
You are trying to modify a string literal which invokes Undefined Behavior
char *array="Mike"; /* String Literal is stored in read only section of memory */
*array='P'; /* Undefined Behavior */
C99 Section 6.4.5.6 (Section-- String Literals) clearly states:
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
Whereas,
char array[5] = "Mike";/*Creates a local array and copies the string "Mike" into it*/
*array='P';/*Fine*/
When you declare a character array, the memory is allocated on the stack and you can write to that.
When you later call malloc(), you allocate memory in the heap and you can write to that.
When you do the thing in the middle that crashes, you've declared a pointer to a string that lives in memory you're not allowed to change. It is static and read-only.

Resources