First of all I know that this is UB and technically anything could happen. But regarding this code snippet compiled with -O0 for target x86_64-linux-gnu, why does this never print "truthy"?
#include <stdio.h>
#include <stdbool.h>
int test(void)
{
bool value;
if (value)
{
printf("truthy");
}
printf("Value: %d", value);
}
int main(void)
{
double buffer[80000];
buffer[10] = 0;
test();
}
I would expect value to be basically random, what am I missing?
EDIT: I'm talking about C here, but if there are any differences with C++ I'm interested in those as well.
I would expect value to be basically random, what am I missing?
When the C standard says the behavior is undefined, it means only that the C standard does not specify anything about the behavior. In particular, it says nothing about whether anything else specifies or affects the behavior.
The absence of a statement about what something does is not a valid reason to infer it would be random.
In general-purpose multiuser systems, when a process requests memory, it is generally provided in two ways (perhaps excepting special requests): For code or initialized data, it is read from the executable file of the program into memory. For uninitialized data, the operating system usually cannot provide uninitialized memory. This is because memory is shared by processes: It is at one time used by one process and later used by another process. The operating system has an obligation to keep the data of processes confidential (unless they specifically request to share memory). So, whenever the operating system gives memory to a process, it must initialize it to non-sensitive data. That is most often done by setting all of it to zero.
So, when a process starts in such a system, the memory used for its stack and for other uninitialized data will actually contain zeros. When a C program starts, there is some initialization code that executes before the main
routine. That code may use some of the stack for its own purposes, so, when main
is called after that initial code, not everything on the stack will be zero. So, if you attempt to observe the values of uninitialized objects on the stack at the start of your program, you may see some of them have non-zero values, but zero values will be very common.
Later in your program, after various routines have been called and have returned, your stack will have been used for multiple purposes, leaving behind a variety of data, and it is less likely that uninitialized objects on the stack will appear to have zero values.
This is an important lesson: While the C standard does not specify the behavior here, the behavior is affected by requirements of the operating system, by how the C environment is implemented, and by other factors. It is usually not random; it largely a consequence of things we can learn about.