How does my OS know if a defined variable is initialized or not?

99 Views Asked by At

At the moment I am messing around a little bit with Sorting Algorithms in C. In the course of this I have run into the following problem: I have defined an int array with

int array[LENGTH];

where LENGTH is a globally defined variable. Then I am trying to change the first element of the array.

array[0] = 1;

When compiling with gcc and executing I am facing a segmentation fault. And after executing the binary file with valgrind I am given the following error:

Conditional jump or move depends on uninitialised value(s)

As I run valgrind again, now with the flag --track-origins=yes, valgrind leads me to the exact line where the initial array was defined.

Doing the same thing on the heap does not change anything:

int* array = (int*) malloc(LENGTH*sizeof(int));
*(array+0) = 1;
...
free(array)

However, I was always told that my OS does not distinguish between initialised and uninitialised variables and that it instead simply reads whatever garbage is stored at the allocated storage segment, no matter if the value at the address of the array (on the stack or heap) was set or not.

Now I am confused. How does my system recognise if a variable at a certain location is initialised? Or am I on the the completely wrong path and storage on the stack and heap is only allocated when initialising a variable (this would explain alot)?

Thanks for the help!

3

There are 3 best solutions below

3
Marco Bonelli On

How does my system recognise if a variable at a certain location is initialised?

The OS does not know.

Valgrind however emulates the machine code (instructions) that are executed by your program and realizes that you are reading something from a memory address where you have never written anything before (and that does not belong to a program segment that is automatically initialized on program start), so it considers it as reading uninitialized data.

If, after detecting a read of uninitialized data, Valgrind encounters instructions that depend on such data, it will emit a warning such as the one you are seeing.

1
John Bollinger On

How does my system recognise if a variable at a certain location is initialised?

Your system does not know. Valgrind knows when you run your program under its supervision, because it watches. And that is costly, sometimes extremely so.

Or am I on the the completely wrong path and storage on the stack and heap is only allocated when initialising a variable (this would explain alot)?

I'm not sure I know what you mean by that. Semantically, space is allocated for automatic variables when control reaches their declarations. Space is allocated for static-duration variables before the beginning of program execution. The space for automatic variables is initialized when allocated if and only if the declaration includes an initializer.

0
Paul Floyd On

Valgrind, and in this case memcheck, is a fairly complete virtualization environment. It replaces calls to malloc so it can track heap memory allocations and deallocations. It follows the stack pointer so it knows when space has been made available on the stack. And it knows the state of all of the registers.

In addition to heap memory, stack memory and registers it also maintains a shadow state for all of these. At the simplest level that will be a bitmap that has one bit (initialized or uninitialized) for each byte of memory/registers. Every time there is a read or write that shadow state will be updated. That means that it always knows what memory/registers are initialized.

When your test executable has debug information (compiled with -g or similar) Valgrind can read that information to allow it to work out the name of the source file and line number associated with the declaration of the variable causing the problem.

Strictly speaking, heap memory on Linux is not allocated until it is written. That is handled by the kernel and is usually transparent (unless you run out of memory and the OOM killer kicks in).