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
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 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 7 years ago.
I made the following little program:
#include <stdio.h>
void strncpy(char * s, char * t, int n);
int
main()
{
char string1[]="Learning strings";
char string2[10];
strncpy(string2,string1,3);
printf("string1:%s\nstring2:%s\n",string1,string2);
return 0;
}
void strncpy(char * s, char * t, int n)
{
int i;
for(i=0; i<n && t[i]!=0;i++)
s[i]=t[i];
s[i]=0;
}
I was trying to learn the difference between doing something like:
char greeting[]="Hello!";
And
char * farewell="Goodbye!";
And I thought my program would work with either of the two types of 'strings'(correct way of saying it?), but it only works with the first one.
Why does this happen? What's the difference between the two types?
What would I have to do to my program to be able to use strings of the second type?
The statement
char greeting[] = "Hello!";
causes the compiler to work out the size of the string literal "Hello!" (7 characters including the terminating '\0'), create an array of that size, and then copy that string into that array. The result of that greeting can be modified (e.g. its characters overwritten).
The statement
char * farewell="Goodbye!";
creates a pointer that points at the first character in the string literal "Goodbye!". That string literal cannot be modified without invoking undefined behaviour.
Either greeting or farewell can be passed to any function that does not attempt to modify them. greeting can also be passed to any function which modifies it (as long as only characters greeting[0] through to greeting[6] are modified, and no others). If farewell is modified, the result is undefined behaviour.
Generally speaking, it is better to change the definition of farewell to
const char * farewell="Goodbye!";
which actually reflects its true nature (and will, for example, cause a compilation error if farewell is passed to a function expecting a non-const parameter). The fact that it is possible to define farewell as a non-const pointer while it points at (the first character of) a string literal is a historical anomaly.
And, of course, if you want farewell to be safely modifiable, declare it as an array, not as a pointer.
The string literals "Hello" and "Goodbye" are stored as arrays of char such that they are allocated at program startup and released at program exit, and are visible over the entire program. They may be stored in such a way that they cannot be modified (such as in a read-only data segment). Attempting to modify the contents of a string literal results in undefined behavior, meaning the compiler isn't required to handle the situation in any particular way - it may work the way you want, it may result in a segmentation violation, or it may do so ething else.
The line
char greeting[] = "Hello";
allocates enough space to hold a copy of the literal and writes the contents of the literal to it. You may modify the contents of this array at will (although you can't store strings longer than "Hello" to it).
The line
char *farewell = "Goodbye";
creates a pointer and writes the address of the string literal "Goodbye" to it. Since this is a pointer to a string literal, we cannot write to the contents of the literal through that pointer.
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:
Closed 11 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
More of a general question rather than trying to fix something, I've been reading the C programming language book and they take care to make the distinction between
char amessage[] = "blah";
char *pmessage = "blah";
The difference being one is a char array and the other a pointer to a string constant. They say modifying the char array is acceptable but you shouldn't modify string constants as it triggers undefined behavior. My question is: isn't the string constant stored in memory the same way the char array is? Why can I modify it as in
char *p = "this is a string constant";
*(p+2) = 'a';
printf("%s", p);
Ends up printing "thas is a string constant" as you might expect. I can understand how it would make sense as a string constant shouldn't end up being changed at run time, as it might confuse others/yourself working on your code not expecting it's value to change but in purely functional terms what is wrong with it, what is the undefined behavior that might trigger and how mechanically could it backfire when a char array wouldn't? I'm just wondering if I'm missing something about how string constants work in memory and how they are seen by the compiler.
At least on my computer, the following program crashes:
#include <stdio.h>
int main() {
char *p = "this is a string constant";
*(p+2) = 'a';
printf("%s", p);
}
If it appears to be working for you (which it might on certain embedded compilers), you're just getting lucky. Undefined behavior means the program is allowed to do anything. See http://blog.regehr.org/archives/213 .
See also What is the difference between char s[] and char *s?.
In case of char array the content of the string literal "blah" are copied on to the stack as well. So you can modify it without invoking UB because after all its just a copy.
In case of char * you actually try to modify the original string literal and as per the Standard that is UB.
With a string constant, there's not guarantee about where the data will be stored -- the compiler is free to do any tricks it wants, because you're supposed to be forbidden from writing to it. So for example, it's not unheard of for the pointer to actually point to the spot in the loaded executable code itself where the string constant is defined.
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.