Damian Siniakowicz
Damian Siniakowicz

Reputation: 127

What does C++ do at the memory address of a variable to "deallocate" it?

For example .
When a function, that has a local integer variable x, ends, what does C++ do to the value stored at memory location corresponding to x?
Does it insert a random value?

Upvotes: 7

Views: 462

Answers (7)

Kethiri Sundar
Kethiri Sundar

Reputation: 500

The object won’t be actually removed from the memory even after delete call. This is a vulnerability and sensitive informations can be leaked via dump files. So it is always a best practice to replace sensitive objects with a dummy and delete it.

Upvotes: 1

Fantastic Mr Fox
Fantastic Mr Fox

Reputation: 33854

This very much depends on the implementation.

In most cases nothing is done. You deallocate (which changes the stack pointer). You don't modify the memory in this case.

In some very obscure cases you may find different things done. In one example, the RTOS RTEMS can be set up to write to the memory in dealocation. It might write something specific like 0xCDCDCDCD or 0xDEADBEEF. This can be helpful when debugging memory issues in these RTOS systems because it is easy to identify when you are using bad memory. But this is very rare.

Upvotes: 4

user3344003
user3344003

Reputation: 21607

This behavior is not defined by C++ but every implementation I am aware of does something like this.

The compiler determines how many byte are needed for the local variables in the function. The compiler creates prolog code that does something like this:

  SUB #NUMBEROFNEEDEDBYTES, SP

That allocates the storage from the stack.

Internally, the compiler assigns some offset to each variable. Let's say:

 X=12

Then

 12(SP) 

becomes the address of X.

 ADD #4, 12(SP)

is equivalent to

X += 4 ;

At the end of the function the compiler creates epilog code that does something like:

 ADD #NUMBEROFNEEDEDBYTES, SP

To free the memory.

X then has the initial value of whatever happened to be on the stack at that location. Whatever you put in X remains for the next function.

Upvotes: 1

Michael Veksler
Michael Veksler

Reputation: 8475

In theory this is not specified, but in practice no allocation is taking place for individual basic-type objects like int, double, T*, etc. In some cases, the stack pointer is not modified and the compiler simply reuses the space for other variables:

for (int i=0 ; i < 10 ; i++)
   foo(i);
for (int j=0 ; j < 10 ; j++)
   foo(j);

Most likely, the compiler will reuse the space of i for allocating j. This is easily verified on godbolt.org with gcc:

.L2:
        mov     edi, ebx
        add     ebx, 1
        call    foo(int)
        cmp     ebx, 10
        jne     .L2
        xor     ebx, ebx
.L3:
        mov     edi, ebx
        add     ebx, 1
        call    foo(int)
        cmp     ebx, 10
        jne     .L3

Not only the loops are identical, they don't even use the stack. Instead of the stack, both i and j variables are allocated on the `ebx. In this example, allocation and deallocation are completely transparent and are a simple use or no-use of registers.


A more complicate example will do the same on the stack:

int foo(int);
void bar(int*);
void bar()
{
    {
        int a[10];
        for (int i=0 ; i < 10 ; i++)
            a[i] = foo(i);
        bar(a);
    }
    {
        int b[10];
        for (int j=0 ; j < 10 ; j++)
            b[j] = foo(j);
        bar(b);
    }
}

Also, consulting second godbolt.org example produces:

        xor     ebx, ebx ; <--- this is simply part of the next block
        sub     rsp, 48;   <--- allocating the stack space
.L2:
        mov     edi, ebx
        call    foo(int)
        mov     DWORD PTR [rsp+rbx*4], eax
        add     rbx, 1
        cmp     rbx, 10
        jne     .L2
        mov     rdi, rsp
        xor     ebx, ebx ; <--- this is simply part of the next block
        call    bar(int*)
.L3:
        mov     edi, ebx
        call    foo(int)
        mov     DWORD PTR [rsp+rbx*4], eax
        add     rbx, 1
        cmp     rbx, 10
        jne     .L3
        mov     rdi, rsp
        call    bar(int*)
        add     rsp, 48  ; <-- deallocating the stack space

Here also, the code is identical for the two cases. There is no deallocation or allocation of the variables on the stack. The line:

        a[i] = foo(i);

is translated into

        mov     DWORD PTR [rsp+rbx*4], eax

which simply writes data relative to the stack pointer (rsp). It basically finds the contents of a according to its position relative to the stack pointer. The stack pointer is not updated between the two blocks of code, it is only passed to bar() by copying the stack pointer to rdi:

        mov     rdi, rsp
        call    bar(int*)


As I have shown, usually during the running of a block no allocation and deallocaiton take place. Typically, at the beginning and the end of a function, the stack-pointer is updated to reflect the variables.

Unlike simple integer values, types with destructors are more complicated, but I will not go deeper on that because it was not asked in the question.

Upvotes: 3

Kethiri Sundar
Kethiri Sundar

Reputation: 500

If you are creating an object and allocating a pointer to it

Animal* animal =new Animal() ;

It will allocate a memory region in the memory.It is like you are building a house and giving address to someone.

delete animal;

Will go to that memory region and destroy it.Like you trace the house with the address and destroying it. Then the value it holds will be garbage. As a good practice you have to make the address of the house nullptr.

animal = nullptr;

Upvotes: 2

sagi
sagi

Reputation: 40471

What's probably happening - is nothing. Deleting something takes resources, so instead it just adjusts the pointer of the stack that is pointing to this memory. This will lead to overwriting it next time this memory is used.

You can see a similar thing while using a variable without initializing it.

int i;

i will have "garbage" data in it, this "garbage" is from a time where this specific location in memory was in use. Could be an old photo, a text file or w/e.

Upvotes: 4

user2261597
user2261597

Reputation:

Like user3344003 says, the variable x is allocated on the stack, that is where the stack pointer points. If you don't know what a stack pointer is you need to read up on it. When the function ends, the reference to (all) local variables are lost, including x. Now the memory used as stack is reused and the values of all local variables including x is thus lost both because their refererences (memory addresses on the stack) are lost and also because the memory is reused for other variables or purposes.

Upvotes: 1

Related Questions