Home > Software engineering >  Can my program use unallocated memory on the free store without my knowledge?
Can my program use unallocated memory on the free store without my knowledge?

Time:08-17

When defining a variable without initialization on either the stack or the free store it usually has a garbage value, as assigning it to some default value e.g. 0 would just be a waste of time.

Examples:

int foo;//uninitialized foo may contain any value
int* fooptr=new int;//uninitialized *fooptr may contain any value

This however doens't answer the question of where the garbage values come from. The usual explanation to that is that new or malloc or whatever you use to get dynamically allocated memory don't initialize the memory to some value as I've stated above and the garbage values are just leftover from whatever program used the same memory prior.

So I put this explanation to the test:

#include <iostream>

int main()
{
    int* ptr= new int[10]{0};//allocate memory and initialize everything to 0
    for (int i=0;i<10;  i)
    {
        std::cout<<*(ptr i)<<"   "<<ptr i<<std::endl;
    }
    delete[]ptr;
    ptr= new int[10];//allocate memory without initialization
    for (int i=0;i<10;  i)
    {
        std::cout<<*(ptr i)<<"   "<<ptr i<<std::endl;
    }
    delete[]ptr;
}

Output:

0   0x1291a60
0   0x1291a64
0   0x1291a68
0   0x1291a6c
0   0x1291a70
0   0x1291a74
0   0x1291a78
0   0x1291a7c
0   0x1291a80
0   0x1291a84
19471096   0x1291a60
19464384   0x1291a64
0   0x1291a68
0   0x1291a6c
0   0x1291a70
0   0x1291a74
0   0x1291a78
0   0x1291a7c
0   0x1291a80
0   0x1291a84

In this code sample I allocated memory for 10 ints twice. The first time I do so I initialize every value to 0. I use delete[] on the pointer and proceed to immediately allocate the memory for 10 ints again but this time without initialization.

Yes I know that the results of using an uninitialized variable are undefined, but I want to focus on the garbage values fro now.

The output shows that the first two ints now contain garbage values in the same memory location. If we take the explanation for garbage values into consideration this leaves me only one conclusion: Between deleting the pointer and allocating the memory again something must have tampered with the values in those memory locations.

But isn't the free store reserved for new and delete? What could have tampered those values?

Edit: I removed the std::cout as a comment pointed it out. I use the compiler Eclipse 2022-06 comes with (MinGW GCC) using default flags on Windows 10.

CodePudding user response:

One of the things you need to understand about heap allocations is that there is always a small control block also allocated when you do a new. The values in the control block tend to inform the compiler how much space is being freed when delete is called.

When a block is deleted, the first part of the buffer is often overwritten by a control block. If you look at the two values you see from your program as hex values, you will note they appear to be addresses in the same general memory space. The first looks to be a pointer to the next allocated location, while the second appears to be a pointer to the start of the heap block.

Edit: One of the main reasons to add this kind of control block in a recently deallocated buffer is that is supports memory coalescence. That two int signature will effectively show how much memory can be claimed if that space is reused, and it signals that it is empty by pointing to the start of the frame.

CodePudding user response:

When defining a variable without initialization on either the stack or the free store it usually has a garbage value, as assigning it to some default value e.g. 0 would just be a waste of time.

No. The initial value of a variable that is not initialized is always garbage. All garbage. This is inherent in "not initialized". The language semantics do not specify what the value of the variable is, and reading that value produces undefined behavior. If you do read it and it seems to make sense to you -- it is all zeroes, for example, or it looks like the value that some now-dead variable might have held -- that is meaningless.

This however doens't answer the question of where the garbage values come from.

At the level of the language semantics, that question is non-sensical. "Garbage values" aren't a thing of themselves. The term is descriptive of values on which you cannot safely rely, precisely because the language does not describe where they come from or how they are determined.

The usual explanation to that is that new or malloc or whatever you use to get dynamically allocated memory don't initialize the memory [so the] values are just leftover from whatever program used the same memory prior.

That's an explanation derived from typical C and C implementation details. Read again: implementation details. These are what you are asking about, and unless your objective is to learn about writing C and / or C compilers or implementations of their standard libraries, it is not a particularly useful area to probe. The specifics vary across implementations and sometimes between versions of the same implementation, and if your programs do anything that exposes them to these details then those programs are wrong.

I know that the results of using an uninitialized variable are undefined, but I want to focus on the garbage values fro now.

No, apparently you do not know that the results of using the value of an uninitialized variable are undefined. If you did, you would not present the results of your program as if they were somehow meaningful.

You also seem not understand the term "garbage value", for in addition to thinking that the results of your program are meaningful, you appear to think that some of the values it outputs are not garbage.

  • Related