What Is the Behavior of "Delete" with Stack Objects

Calling delete on variable allocated on the stack

No, it is not safe to call delete on a stack-allocated variable. You should only call delete on things created by new.

  • For each malloc or calloc, there should be exactly one free.
  • For each new there should be exactly one delete.
  • For each new[] there should be exactly one delete[].
  • For each stack allocation, there should be no explicit freeing or deletion. The destructor is called automatically, where applicable.

In general, you cannot mix and match any of these, e.g. no free-ing or delete[]-ing a new object. Doing so results in undefined behavior.

What is the use of delete this?

"delete this" is commonly used for ref counted objects. For a ref counted object the decision of when to delete is usually placed on the object itself. Here is an example of what a Release method would look like [1].

int MyRefCountedObject::Release() {
_refCount--;
if ( 0 == _refCount ) {
delete this;
return 0;
}
return _refCount;
}

ATL COM objects are a prime example of this pattern.

[1] Yes I realize this is not thread safe.

Strange behavior of delete keyword in javascript

Your question is more related to the fact that some types are assigned by value and others by reference.

In a quick summary

Primitive types are assigned by value (Boolean, Null, Undefined, Number, String, Symbol (new in ES 6))

Non Primitive types are assigned by reference (Object, Array , Functions)


Example: Primitive types

let a = 1;
let b = a;

console.log(a); // 1
console.log(b); // 1

b = 2;

console.log(a); // 1
console.log(b); // 2

As you can see changing b will not affect a because number is assigned by value.


Example: Non Primitive types

let a = { name: 'Amr' };
let b = a;

console.log(a); // { name: 'Amr' };
console.log(b); // { name: 'Amr' };

b.name = "John";

console.log(a); // { name: 'John' };
console.log(b); // { name: 'John' };

As you can see changing b affected the value of a because it is assigned by reference, this is similar to your example, the issue is not related to delete but it is related to the fact that objects are assigned by reference so deleting key from b will affect a


Cloning:

in some situations you will need to clone your non primitive type object and not mutating the current one, you can do that using the following way:

  1. ES5 var clone = Object.assign({}, obj); OR
    var clone = JSON.parse(JSON.stringify(obj));

  2. ES6 var clone = { ...obj };

now updating clone will not affect obj


Finally You can read more about this topic in this link it can give you a better understanding on how this works with memory assignment illustrations

Is delete allowed to modify its parameter?

Before the deletion, ptr's value was valid. After the deletion, the value was invalid. Therefore the value changed. Valid values and invalid values are mutually exclusive -- a value cannot be simultaneously valid and invalid.

Your question has a basic misconception; you're conflating these two different concepts:

  • The value of a variable
  • The representation of a variable in memory.

There isn't a one-to-one correspondence between these two things. The same value may have multiple representations, and the same representation may correspond to different values.


I think the gist of your question is: can delete ptr; change the representation of ptr?. To which the answer is "Yes". You could memcpy the deleted pointer into a char array, inspect the bytes, and find them all to be zero-valued bytes (or anything else). This is covered in the standard by C++14 [basic.stc.dynamic.deallocation]/4 (or C++17 [basic.stc]/4):

Any other use of an invalid pointer value has implementation-defined behavior.

It's implementation-defined and the implementation could define that inspecting the bytes gives bytes with value zero.


Your code snippet relies on implementation-defined behaviour. "Valid code" isn't terminology used by the Standard, but the code might not remove the intended item from the hash table.

As alluded to by Stroustrup, this is an intentional design decision. An example usage would be a compiler in debug mode setting deleted pointers to a particular representation, so that it can raise a runtime error if a deleted pointer is subsequently used. Here's an example of that principle in action for uninitialized pointers.

Historical note: In C++11 this case was undefined, rather than implementation-defined. So the behaviour of using a deleted pointer was identical to the behaviour of using an uninitialized pointer. In the C language, freeing memory is defined as putting all pointers to that memory into the same state as an uninitialized pointer has.

Why does calling delete instead of delete[] on an array of class objects cause heap corruption?

It is undefined behavior to call delete on a pointer created with new[]. The basic issue is that when you call new[] it needs to allocate extra space to store the number of elements in the array, so that when you call delete [] it knows how many elements to destroy.

The library will allocate space for the management data in addition to the needed space for the real objects. It will then perform all initialization and return a pointer to the first element, which is not aligned with the block of memory retrieved from the OS.

[header][element1,element2...]
^ ^
| \_ pointer returned by new[]
|
\_ pointer returned by the allocator

On the other hand, new and delete don't store any extra information.

When you call delete[] it moves the pointer back, reads the count, calls the destructors and deallocates using the original pointer. When you call delete, it calls the destructor for the single object and passes the pointer back to the allocator. If the pointer was created through a call to new[], then the pointer that is returned to the allocator is not the same pointer that was allocated and the deallocation fails.

delete[] with different type undefined behaviour?

Yes, the behaviour is undefined.

The pointer passed to delete[] must be the same type as the one you get back from new[].

Note that for delete and new, the pointer submitted to delete is allowed to be related by polymorphism.



Related Topics



Leave a reply



Submit