Running this code
#include <stdlib.h>
#include <stdio.h>
char* f() {
char s[] = "Hello, world!";
return s;
}
int main() {
printf("%s", f());
return 0;
}
prints (null)
. This makes sense to me: The char
array is valid only in the scope of f
, so the pointer returned is not valid. However, if I create a struct containing the pointer to the array
#include <stdlib.h>
#include <stdio.h>
typedef struct word {
char* str;
} word;
word f() {
char str[] = "Hello, world!";
return (word) { str };
}
int main() {
printf("%s", f().str);
return 0;
}
this will now "work", i. e. it will print Hello, world!
.
Now I am wondering why it does; shouldn't the pointer here be invalid too, because the array it points to was created in f
and is thus not valid anymore? Or is this just undefined behavior and I got "lucky" that nothing else was pushed onto the stack at that location? Or is there a mistake in my reasoning (I am rather new to C).
I haven't been able to find information on this specific behavior, only for structs containing arrays of constant size. I have tested this using gcc
version 9.4.0
(which uses gnu11
"standard" as default). I would appreciate if anyone could point me to the explanation of this behavior.
CodePudding user response:
Or is this just undefined behavior and I got "lucky" that nothing else was pushed onto the stack at that location?
That is correct. The line
printf("%s", f().str);
will invoke undefined behavior by dereferencing a dangling pointer. This means that anything may happen; your program may crash or it may appear to work as intended.
The compiler clang is actually able to detect this error at run-time, if you compile with -fsanitize=address
. Here is an online demonstration.
For further explanation, you may want to read this answer to a similar C question, which contains an interesting analogy. Most of the information in the answer also applies to C.