Up vote 22 down vote favorite 7 share g+ share fb share tw.
The following code receives seg fault on line 2: char *str = "string"; str0 = 'z'; printf("%s", str); While this works perfectly well: char str = "string"; str0 = 'z'; printf("%s", str); Tested with MSVC and GCC. C segmentation-fault c-strings link|improve this question edited Feb 2 at 3:40R. Martinho Fernandes35.4k1368124 asked Oct 2 '08 at 19:45Markus11835.
Char a = "string literal"; char *p = "string literal"; My program crashes if I try to assign a new value to pi. A: 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).
K&R section 5.5... Silly me, should have opened the book before asking stupid questions! – Markus Oct 2 '08 at 21:27 it would be nice if you could quote it here... – Nathan Fellman Oct 23 '08 at 8:53 quoted it for him – Simucal Dec 11 '08 at 9:10 Couple of other points: (1) the segfault happens as described, but its occurrence is a function of the run environment; if the same code was in an embedded system, the write may have no effect, or it may actually change the s to a z. (2) Because string literals are non-writable, the compiler can save space by putting two instances of "string" in the same place; or, if somewhere else in the code you have "another string", then one chunk of memory could support both literals.
Clearly, if code were then allowed to change those bytes, strange and difficult bugs could occur. – greggo Aug 26 '11 at 23:24.
Normally, string literals are stored in read-only memory when the program is run. This is to prevent you from accidentally changing a string constant. In your first example, "string" is stored in read-only memory and *str points to the first character.
The segfault happens when you try to change the first character to 'z'. In the second example, the string "string" is copied by the compiler from its read-only home to the str array. Then changing the first character is permitted.
You can check this by printing the address of each: printf("%p", str); Also, printing the size of str in the second example will show you that the compiler has allocated 7 bytes for it: printf("%d", sizeof(str)).
1 Whenever using "%p" on printf, you should cast the pointer to void * as in printf("%p", (void *)str); When printing a size_t with printf, you should use "%zu" if using the latest C standard (C99). – Chris Young Oct 3 '08 at 7:44 Also, the parenthesis with sizeof are only needed when taking the size of a type (the argument then looks like a cast). Remember that sizeof is an operator, not a function.
– unwind Nov 25 '08 at 8:45.
In the first code, "string" is a string constant, and string constants should never be modified because they are often placed into read only memory. "str" is a pointer being used to modify the constant. In the second code, "string" is an array initializer, sort of short hand for char str7 = { 's', 't', 'r', 'i', 'n', 'g', '\0' }; "str" is an array allocated on the stack and can be modified freely.
Because the type of "whatever" in the context of the 1st example is const char * (even if you assign it to a non-const char*), which means you shouldn't try and write to it. The compiler has enforced this by putting the string in a read-only part of memory, hence writing to it generates a segfault.
Char *str = "string"; The above sets str to point to the literal value "string" which is hard-coded in the program's binary image, which is probably flagged as read-only in memory. So str0= is attempting to write to the read-only code of the application. I would guess this is probably compiler dependent though.
The C FAQ that @matli linked to mentions it, but no one else here has yet, so for clarification: if a string literal (double-quoted string in your source) is used anywhere other than to initialize a character array (ie: @Mark's second example, which works correctly), that string is stored by the compiler in a special static string table, which is akin to creating a global static variable (read-only, of course) that is essentially anonymous (has no variable "name"). The read-only part is the important part, and is why the @Mark's first code example segfaults.
Char *str = "string"; allocates a pointer to a string literal, which the compiler is putting in a non-modifiable part of your executable; char str = "string"; allocates and initializes a local array which is modifiable.
Most of these answers are correct, but just to add a little more clarity... The "read only memory" that people are referring to is the text segment in ASM terms. It's the same place in memory where the instructions are loaded. This is read-only for obvious reasons like security.
When you create a char* initialized to a string, the string data is compiled into the text segment and the program initializes the pointer to point into the text segment. So if you try to change it, kaboom. Segfault.
When written as an array, the compiler places the initialized string data in the data segment instead, which is the same place that your global variables and such live. This memory is mutable, since there are no instructions in the data segment. This time when the compiler initializes the character array (which is still just a char*) it's pointing into the data segment rather than the text segment, which you can safely alter at run-time.
String literals like "string" are probably allocated in your executable's address space as read-only data (give or take your compiler). When you go to touch it, it freaks out that you're in its bathing suit area and lets you know with a seg fault. In your first example, you're getting a pointer to that const data.
In your second example, you're initializing an array of 7 characters with a copy of the const data.
The char *str = "string"; line defines a pointer and points it to a literal string. The literal string is not writable so when you do: str0 = 'z'; you get a seg fault. On some platforms, the literal might be in writable memory so you won't see a segfault, but it's invalid code (resulting in undefined behavior) regardless.
The line: char str = "string"; allocates an array of characters and copies the literal string into that array, which is fully writable, so the subsequent update is no problem.
In the first place, str is a pointer that points at "string". The compiler is allowed to put string literals in places in memory that you cannot write to, but can only read. (This really should have triggered a warning, since you're assigning a const char * to a char *.
Did you have warnings disabled, or did you just ignore them? ) In the second place, you're creating an array, which is memory that you've got full access to, and initializing it with "string". You're creating a char7 (six for the letters, one for the terminating '\0'), and you do whatever you like with it.
Create a string constant like this - will be read only char *str_p; str_p = "String constant"; // create an array of characters like this char *arr_p; char arr = "String in an array"; arr_p = &arr0; // now we try to change a character in the array first, this will work *arr_p = 'E'; // lets try to change the first character of the string contant *str_p = 'G'; // this will result in a segmentation fault. Comment it out to work. /*----------------------------------------------------------------------------- * String constants can't be modified.
A segmentation fault is the result, * because most operating systems will not allow a write * operation on read only memory. *-----------------------------------------------------------------------------*/ //print both strings to see if they have changed printf("%s\n", str_p); //print the string without a variable printf("%s\n", arr_p); //print the string, which is in an array.
Char *str = "string"; This creates a string literal str variable and gcc stores this in the read only "text" or "code" segement of the process. So, any modification of this triggers a segmentation fault. When I try this program on Ubuntu Linux with gcc 4.6.1.
Void main() { char *str="hello"; printf("%s %p\n", str, str); fflush(stdout); str0='t'; sleep(20); } Output : hello 0x40071c segmentation fault The address of str is in code/text part of process starting at 00400000( as show below) from the maps file in /proc/3659/maps cat /proc/3659/maps ( Just captured the first 3 lines here...) 00400000-00401000 r-xp 00000000 08:13 1047332 /home/sachin/pg/a. Out code/text part of process, which is read and execute only.. 00600000-00601000 r--p 00000000 08:13 1047332 /home/sachin/pg/a. Out 00601000-00602000 rw-p 00001000 08:13 1047332 /home/sachin/pg/a.
Out data part of process.. all the data initialized and in bss.
Updated with code, output of program and output of maps file on running the program.. – Sachin Mar 28 at 15:14.
Int *p; printf("%d",p); In the above two lines 'p' is a pointer with garbage value. But in second line you are trying to read the value of p pointing to the address. Here you get segmentation fault.
If your program is trying to read the value from another process then the OS will terminate your process forcefully. Another case is that if the p is trying to read value from an out-of-memory location then it causes a segmentation fault.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.