When you write
const char *ptr = "blah blah";
then the following happens: the compiler generates a constant string (of type char []) with the contents "blah blah" and stores it somewhere in the data segment of the executable (it basically has a similar storage duration to that of variables declared using the static keyword).
Then, the address of this string, which is valid throughout the lifetime of the program, is stored in the ptr pointer, which is then returned. All is fine.
Does this mean that
"blah blah"is not a local variable inside getString()?
Let me respond with a broken English sentence: yes, it isn't.
However, when you declare an array, as in
const char a[] = "blah blah";
then the compiler doesn't generate a static string. (Indeed, this is a somewhat special case when initializing strings.) It then generates code that will allocate a big enough piece of stack memory for the a array (it's not a pointer!) and will fill it with the bytes of the string. Here a is actually a local variable and returning its address results in undefined behavior.
So...
But I thought that
const char *ptrandconst char a[]were basically the same thing.
No, not at all, because arrays are not pointers.
Answer from user529758 on Stack OverflowWhen you write
const char *ptr = "blah blah";
then the following happens: the compiler generates a constant string (of type char []) with the contents "blah blah" and stores it somewhere in the data segment of the executable (it basically has a similar storage duration to that of variables declared using the static keyword).
Then, the address of this string, which is valid throughout the lifetime of the program, is stored in the ptr pointer, which is then returned. All is fine.
Does this mean that
"blah blah"is not a local variable inside getString()?
Let me respond with a broken English sentence: yes, it isn't.
However, when you declare an array, as in
const char a[] = "blah blah";
then the compiler doesn't generate a static string. (Indeed, this is a somewhat special case when initializing strings.) It then generates code that will allocate a big enough piece of stack memory for the a array (it's not a pointer!) and will fill it with the bytes of the string. Here a is actually a local variable and returning its address results in undefined behavior.
So...
But I thought that
const char *ptrandconst char a[]were basically the same thing.
No, not at all, because arrays are not pointers.
I guess that if it were a local variable, I would not be able to pass it to my main() function... But if it's not, where is it stored?
String literals are usually stored in a read-only data section (.rodata). C standard just say they have static storage duration. Therefore you can return a pointer to such literal, but it is not the case of arrays.
In the following example, the object pointed by p1 has static storage duration, whereas the array p2 has automatic storage duration.
char *f(void)
{
const char *p1 = "hello, world";
char p2[] = "hello, world";
return p1; /* allowed */
return p2, /* forbidden */
}
Edited to add another question about pointing to local variables with global pointers. This has been solved. The solution I found is at the end.
From what I understand, I can do the following:
char *myString = ""; myString = "Hello World"; myString = "Goodbye";
And this would not be wrong. However, thinking a bit into it, it makes no sense to me, because when/how is memory being allocated/rellocated/freed for this? First of all I make a string with 0 chars, so it needs 0 bytes. Then it needs ~11 bytes, then only 7. The memory needed to store the string is changing, but at no point in time have I done anything with memory, so is C managing it in the background? Does C not manage it and therefore this is wrong? What would happen if I now did myString=NULL;? Would that leave allocated memory with no one pointing to it?
To hijack my own post and not spam, an additional question about memory. If I create a variable inside a function, say int myLocalInt;, C automatically reserves memory for that variable to be stored in, so I don't need to do any malloc shit. If I then declare a pointerint *myLocalIntPtr;, I can make that pointer point to that variable's memory (myLocalIntPtr=&myLocalInt) and I wouldn't need to do malloc, right?And now for the important question. In the previous example with the local int, what would happen if I assigned a global pointer the memory address of the local int when the function the int is local to ends?
int *globalPtr;
int someFunction(){
int myLocalInt = 5;
globalPtr = &myLocalInt;
printf("Of course this would print 5: %d",*globalPtr);
return 0;
}
int main(){
someFunction();
printf("But what about now? Is it still 5? i=%d",*globalPtr);
}I just realized I can test that myself, so I'll go do that. Beside that, I understand that C releases all local variables when their block ends, but given that there's still a pointer to it I thought it might not.
If it was freed, globalPtr would now be aiming at non-allocated memory, which is a problem. Especially because I don't know how to check if a block of memory is currently allocated. (I guess I could try calling free on it, and if there's an error it's not allocated). I understand this would give undefined behaviour, with it being possible that the print outside still gives 5, or it might give some other number if the memory has been altered, or could give an error.
Testing did not help much, however thinking did. It seems memory allocated to local variables will always be freed when the local variable goes out of scope. However, if the variable is a pointer, and it was allocated memory with malloc or any of those, that memory is still reserved. So the solution in my case is to declare pointers to the types I needed instead of the types themselves. I thought I was being cheeky by declaring the variables of the type directly and avoiding memory management, but it backfired.
Hey,
const char * text = “test“;
how is a string literal stored? I once catched up, that it is stored in a constant memory section.
If i would define a function like this:
void foo(const char * text) { }
and then call this function infinitely with foo(“test“), does this can lead to memory overflow or something? Because the string i put in this function is stored everytime again and again, and so the memory would be full?
Or would this only be, if i put different strings in the function and call it infinitely?
A common technique is for string literals to be put in "read-only-data" section which gets mapped into the process space as read-only (which is why you can't change it).
It does vary by platform. For example, simpler chip architectures may not support read-only memory segments so the data segment will be writable.
Rather than try to figure out a trick to make string literals changeable (it will be highly dependent on your platform and could change over time), just use arrays:
char foo[] = "...";
The compiler will arrange for the array to get initialized from the literal and you can modify the array.
Why should I not try to alter it?
Because it is undefined behavior. Quote from C99 N1256 draft 6.7.8/32 "Initialization":
EXAMPLE 8: The declaration
char s[] = "abc", t[3] = "abc";defines "plain" char array objects
sandtwhose elements are initialized with character string literals.This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";defines
pwith type "pointer to char" and initializes it to point to an object with type "array of const char" with length 4 whose elements are initialized with a character string literal. If an attempt is made to usepto modify the contents of the array, the behavior is undefined.
Where do they go?
GCC 4.8 x86-64 ELF Ubuntu 14.04:
char s[]: stackchar *s:.rodatasection of the object file- the same segment where the
.textsection of the object file gets dumped, which has Read and Exec permissions, but not Write
Program:
#include <stdio.h>
int main() {
char *s = "abc";
printf("%s\n", s);
return 0;
}
Compile and decompile:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
Output contains:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
So the string is stored in the .rodata section.
Then:
readelf -l a.out
Contains (simplified):
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000704 0x0000000000000704 R E 200000
Section to Segment mapping:
Segment Sections...
02 .text .rodata
This means that the default linker script dumps both .text and .rodata into a segment that can be executed but not modified (Flags = R E). Attempting to modify such a segment leads to a segfault in Linux.
If we do the same for char[]:
char s[] = "abc";
we obtain:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
so it gets stored in the stack (relative to %rbp), and we can of course modify it.