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 7 years ago.
Today when learning pointer in C, I have faced a problem. I wrote this code:
#include<stdio.h>
int main()
{
char *p="XAD";
printf("%c\n",(*p));
printf("%c\n",++(*p));
return 0;
}
First printf() shows correct output and it is X. But for second output, compiler crashes. But why? If (*p) gives 'X'(as expected), then ++(*p) should give 'Y'. Shouldn't it?
Here:
char *p="XAD";
You create a pointer p and assign it to the string literal "XAD". String literals are immutable, meaning that it cannot be changed. The ++(*p) dereferences the pointer p and increments it, thus attempting to change the contents of the string literal (Specifically, the first character). Attempting to modify a string literal leads to Undefined Behavior as seen in the C11 standard (emphasis mine):
6.4.5 String literals
[...]
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
Fix the problem by either declaring p as an array or using (*p)+1 instead of ++(*p). Using the former will not modify the contents of the string literal while the latter does.
The pointer p points to a string literal. Modifying a string literal results in undefined behaviour in C.
Change
char *p="XAD";
to
char p[]="XAD";
which will allow you to modify it since p is an array here.
While char *p="abc"; is perfectly valid in C, in general, string literals should be declared with const keyword as you are not allowed to modify it anyway. This will help catch an accidental change. It should have been of type const char[] but it is of type char [] is because of "historical" reasons (C++ corrected it).
Or you simply interested in printing a modified value, you can do:
printf("%c\n", (*p) + 1);
as suggested by #alk, which does what you code attempts to do but without modifying the string itself.
Related
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 10 months ago.
#include <stdio.h>
#include <stdlib.h>
int main() {
char *str="hello";
str[0]='H';
return 0;
}
If I use an array I can do use subscript to assign the first character. What's different about using a char pointer here that causes a segmentation fault?
In this code snippet
char *str="hello";
str[0]='H';
you are trying to change a string literal pointed to by the pointer str. Any attempt to change a string literal results in undefined behavior.
From the C Standard (6.4.5 String literals)
7 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.
So though in C opposite to C++ string literals have types of non-constant arrays it is always better to declare pointers to string literals with the qualifier const.
const char *str="hello";
You could declare a character array initialized by the string literal and change the array itself like
char str[] ="hello";
str[0]='H';
okay, I got the answer from this wiki - https://en.wikipedia.org/wiki/Segmentation_fault#Writing_to_read-only_memory
The char pointer declared like that writes to a read-only segment of the process, editing that gives a segmentation fault (specifically SEGV_ACCERR which is defined as invalid permissions for mapped object (see here)
An array on the other hand similarly allocated will be done so on the stack and so can be edited.
This question already has answers here:
Modify a string with pointer [duplicate]
(4 answers)
Closed 5 years ago.
I am getting segmentation fault when running the below code. What could be the reason for this error? Please help
int main()
{
char *str2 = "Hello";
str2[3] = 'J';
printf("%s\n",str2);
return 0;
}
It is a undefined behaviour because you are trying to modify the content of a string literal. A string literal mainly stored in a read only location. so you do not modify it, otherwise it is invoked undefined behaviour.
C11 §6.4.5 String literals(Paragraph 7):
It is unspecified whether these arrays are distinct provided their
elements have the appropriate values.If the program attempts to
modify a string literal of either form, the behavior is undefined"
You aren't allowed to modify a string constant, and in this case it's causing a runtime error. You can fix it by changing the declaration of str2 to:
char str2[] = "Hello";
This makes it an array, rather than a pointer to a string constant.
You are not allowed to modify the memory pointed to by char* variables initialized with string literals. It is read-only.
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
This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Closed 9 years ago.
char *p = "string literal"; p[0] = 'S';
char a[] = "string literal"; a[0] = 'S';
What is the main difference between these two?
What really happens in the memory when these two are defined?
Why modifying the first one results in undefined behavior?
I read somewhere that first one may store in read-only memory; my question is: how does that happen?
p points to a character string literal which should not be modified; a is a character array which may be modified.
The character string literal may well be in a read-only section of your program (often the 'text' segment along with the rest of the code), whereas the character array is stored in modifiable memory.
You are not allowed to modify string literals; doing so invokes undefined behaviour.
Often, the string is stored in the 'text' segment, along with the executable code.
It is important to realize that the standard simply says 'thou shalt not modify string literals' (more or less), and attempts to do say may lead to any effect. It is possible that your program will crash (segmentation violation or equivalent); it is possible that your code will modify the literal; it is possible that your code will neither crash nor change the literal. Note that if there are multiple places in the program where the literal occurs, it is possible that modifying one will modify them all — the compiler is allowed to have string literals sharing space in memory. They don't even have to be identical; "string literal" and "literal" could be pointers to different parts of the same string in memory.
ISO/IEC 9899:2011, §6.4.5 String literals says:
¶6 In translation phase 7, a byte or code of value zero is appended to each multibyte
character sequence that results from a string literal or literals. The multibyte character
sequence is then used to initialize an array of static storage duration and length just
sufficient to contain the sequence. [...]
¶7 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.
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