I'm a little bit confused about this expression:
char *s = "abc";
Does the string literal get created on the stack?
I know that this expression
char *s = (char *)malloc(10 * sizeof(char));
allocates memory on the heap and this expression
char s[] = "abc";
allocates memory on the stack, but I'm totally unsure what the first expression does.
Typically, the string literal "abc" is stored in a read only part of the executable. The pointer s would be created on the stack(or placed in a register, or just optimized away) - and point to that string literal which lives "elsewhere".
"abc"
String literals are stored in the __TEXT,__cstring (or rodata or whatever depends on the object format) section of your program, if string pooling is enabled. That means, it's neither on the stack, nor in the heap, but sticks in the read-only memory region near your code.
char *s = "abc";
This statement will be assign the memory location of the string literal "abc" to s, i.e. s points to a read-only memory region.
"Stacks" and "heaps" are implementation details and depend on the platform (all the world is not x86). From the language POV, what matters is storage class and extent.
String literals have static extent; storage for them is allocated at program startup and held until the program terminates. It is also assumed that string literals cannot be modified (attempting to do so invokes undefined behavior). Contrast this with local, block-scope (auto) variables, whose storage is allocated on block entry and released on block exit. Typically, this means that string literals are not stored in the same memory as block-scope variables.
Related
Say I do this:
const char *myvar = NULL;
Then later
*myval = “hello”;
And then again:
*myval = “world”;
I’d like to understand what happens to the memory where “hello” was stored?
I understand it is in the read only stack space, but does that memory space stays there forever while running and no other process can use that memory space?
Thanks
Assuming you meant
myval = "world";
instead, then
I’d like to understand what happens to the memory where “hello” was stored?
Nothing.
You just modify the pointer itself to point to some other string literal.
And string literals in C programs are static fixed (non-modifiable) arrays of characters, with a life-time of the full programs. The assignment really makes the pointer point to the first element of such an array.
String literals have static storage duration. They are usually placed by the compiler in a stack pool. So string literals are created before the program will run.
In these statements
*myval = “hello”;
*myval = “world”;
the pointer myval is reassigned by addresses of first characters of these two string literals.
Pat attention to that you may not change string literals. Whether the equal string literals are stored as a one character array or different character arrays with the static storage duration depends on compiler options.
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.
char *p = "hello";
p = "hello_2";
Here string "hello" was stored in memory and its address was present in pointer 'p' but when this pointer starts pointing to string "hello_2", what will happen to the memory where the string "hello" was stored? Will it be freed or this string remains there but we can't access it?
What you have is a string constant and it is stored in read-only memory.
So this memory is not required to be freed explicitly using free()
Till the lifetime of the variable p is valid you can access the stored string.
The memory will not be freed. But would not (in this case), be lost. The code knows where the string is, and uses it each time the fragment is run, to assign to the pointer p.
Memory which is on the heap does need to be freed (result of malloc or strdup).
Memory which is on the stack does not need to be freed.
Memory which is static (this case) does not need to be freed.
You are actually creating a string literal named "hello" allocating it somewhere in the memory , and assigning the address of first character of the literal to the pointer p, and as the pointer is not constant you can assign it again with different addresses. And one more important point to note is that the string literal created are in read only memory.
There are different memory sections to which the globals, heap, code and string literals go to. It is specific to the compiler used.
gcc makes a .rodata section which is a read-only section and the string literals are stored there.
Visual C++ creates a .rdata section for the read only section.
You can use objdump (on linux) to check different sections for your binary.
I feel confusion about the swap two characters in one string with C.
It works well when I set it as an array:
char strBase[8] = "acbdefg";
in this case I could swap any character.
But it trigger the bus error when I set it as a string:
char *strBase = "acbdefg";
Thanks a lot for anyone could explain it or give me some hint!
The difference here is that
char *strBase = "acbdefg";
will place acbdefg in the read-only parts of the memory and making strBase a pointer to that, making any writing operation on this memory illegal.
It has no name and has static storage duration (meaning that it lives for the entire life of the program); and
a variable of type pointer-to-char, called strBase, which is initialised with the location of the first character in that unnamed, read-only array.
While doing:
char strBase[8] = "acbdefg";
puts the literal string in read-only memory and copies the string to newly allocated memory on the stack.
So this array is allocated in memory, and how long it lives for, depends on where the declaration appears. If the declaration is within a function, it will live until the end of the block that it is declared in, and almost certainly be allocated on the stack; if it's outside a function, it will probably be stored within an "initialized data segment" that is loaded from the executable file into write able memory when the program is run.
Making
strBase[0] = 'x';
legal.
Your problem is one of memory allocation. You need space to store your characters. When you wrote:
char strBase[8] = "acbdefg";
you created automatic storage (often called the stack) and initialized it with a string of characters. But when you wrote:
char *strBase = "acbdefg";
you created a pointer and pointed it at a constant string. The compiler puts that in a part of memory that is marked as read-only. If you try to change that it will result in a memory access violation.
Instead you could do something like:
const char* strData = "acbdefg";
int size = 1024;
char *strBase = (char*)malloc(size);
strncpy(strBase, strData, size);
ProcessString(strBase);
free(strBase);
The most likely cause is that
char strBase[8] = "abcdefg";
causes the compiler to reserve memory for an eight-character array, and initializes it with the value "abcdefg\0". In contrast,
char *strBase = "abcdefg";
only reserves memory for a pointer, initialized with the address of the string. "abcdefg" is a constant string, and as a result, the compiler stores it in a section of memory that gets marked read-only. Attempting to modify read-only memory causes a CPU fault.
Your compiler should be giving you a warning about const mismatch in the second case. Alternatively, your compiler may have a setting that changes the read-only-ness of constant strings.
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.
Consider this function:
void useless() {
char data[] = "aaa";
}
From what I learned here, the "aaa" literal lives to the end of the program. However, the data[] (initialized by the literal) is local, so it lives only to the end of the function.
The memory is copied, so the program needs 4B for the literal, 4B for the data and sizeof(size_t) bytes for the pointer to data and sizeof(size_t) for the pointer of the literal - is this true?
If the literal has static storage duration, no new memory is allocated for the local literal by the second call - is this true?
char data[] = "aaa";
This is not a string literal but just an array. So there's no pointer there and memory is allocated only for the data.
If the literal has static storage duration, no new memory is allocated
for the local literal by the second call
This is true for string literals like: char *s="aaa"; From the standard:
2.13. Sttring literals
[...]An ordinary string literal has type “array of n const char” and static storage duration (3.7)
There is no pointer variable here. All there is an array, which is 4 bytes.
The compiler may or may not store the literal itself in memory; if it does, that is another 4 bytes.
Note that any memory taken up by anything other than the array itself is implementation-dependent.
I'm not sure what you mean by the "second call", but in general when you create an array, it takes up some amount of size... so if you create two arrays with the same literal, the compiler allocates space for two arrays (and perhaps -- or perhaps not -- for the literal also).