-3

So I know that heap is where the memory is stored. Unlike stack, if the user does not delete the heap, the heap keeps existing.

However, I have problem with "an object has been returned back to the memory heap" part. Does returned back means that the object has been freed? If not, why it is a disaster to have a pointer/reference to that object?

  • related - https://stackoverflow.com/questions/2583656/what-is-the-meaning-of-wild-pointer-in-c – sashoalm Sep 24 '16 at 07:04
  • I'm sorry but I still don't understand how it is related to an object that has been returned to the memory heap part? Can you please extend it? @sashoalm – GoldenArcher Sep 24 '16 at 07:08
  • 1
    Yes, that means it's been freed. The memory may still be hanging around however and at some unspecified time the heap may re use it for a subsequent allocation. – Steve Sep 24 '16 at 07:17
  • @Steve thank you so much! – GoldenArcher Sep 24 '16 at 07:18
  • The memory that was freed can change its content any time (f.e. it is allocated for another object that stores whatever it needs there) and your pointer now points to memory that contain garbage data (from its point of view). – axiac Sep 24 '16 at 07:42

2 Answers2

2

Firstly, heap and stack are not C++ concepts. They refer to particular types of memory, as managed on some systems.

Second, what is often described as "heap" is, in C++, referred to as "dynamically allocated memory".

When dynamically allocated memory is released by the program (e.g. using operator delete on something obtained using operator new, using free() on a pointer returned by C's malloc()) that memory no longer exists as far as your program is concerned, but the pointer value does not change. Using a pointer or reference to something that no longer exists gives, in the language of the C++ standard, undefined behaviour.

Practically, the memory might exist physically on your system, or even still be allocated by the host system to your program. However, once it has been released by your program, there is nothing preventing the memory being reused. Your program might use operator new to allocate more memory, so the memory that was previously released is now being used for something else - completey unrelated to the original usage - by your program. That is inherently dangerous - the results can be anything (which is, loosely, the implication of undefined behaviour in the C++ standard).

The operating system might also have recovered the logical or physical memory (after all, your program has indicated no more use for that memory) and allocated it to another program. That is dangerous for both your program and the other program that has been allocated memory. Which is why most modern operating systems prevent that e.g. by forcably terminating your program if the operating system detects an access to memory it no longer owns.

A real danger is that you might access a released object for a while, and everything seems to work as required. Only to crash later on. There can often be a significant time interval between some memory being released by your program, and being reused for something else.

Such flaws in programs tend to infuriate users of that program (users, for some obscure reason, tend to be less than appreciative when programs crash in unpredictable and unrepeatable ways in the middle of their work). Such flaws in your code also tend to be very difficult to track down, and therefore hard to correct.

Peter
  • 35,646
  • 4
  • 32
  • 74
1

I have problem with "an object has been returned back to the memory heap" part. Does returned back means that the object has been freed? If not, why it is a disaster to have a pointer/reference to that object?

It might help to break down the terminology and clarify a few things:

Firstly, the term Object in C++ refers to something residing in memory, but does not refer to the memory itself.

It's worth making a distinction between an object and the memory storing the object because the actions of allocating memory and initialising an object are distinct and separate.

The following line is doing two things:

new int(123);
  • It is allocating an area of memory on the heap to your program whose size in bytes is equal to sizeof(int). The effect of the allocation of memory is not to create an object, nor is it even to change anything about the content of that memory; it is simply to ringfence that memory for your program to use.
    Any "junk" or garbage values which might have been pre-existing in that memory will not be changed.

  • After the memory is allocated, that chunk of memory is initialised with an int object containing 123. Objects may only be initialised within an area of memory which is already allocated to your program.

Given that the new operator is doing two different things, it follows that the delete operator may also perform two different actions:

  • delete will destroy the object; this is usually limited to releasing resources owned by the object. Destroying an object typically does not bother to change or reset any memory which is about to be deallocated because that's usually a waste of CPU cycles.
    After an object is destroyed, you might find the remains or partial remains of that object stuck around in memory for a while, but as far as your program is concerned, the object itself is dead/gone and the memory contents are junk.

  • delete will de-allocate the memory. The process of de-allocation is not to change the content of that memory, it is simply to release that memory for use by something else. Trying to access that area of memory after it has been deallocated is undefined behaviour.


Remember that a pointer cannot ever point-to an object because an object is "The thing in memory" rather than the memory itself; raw pointers in C++ are fairly simple/dumb - they don't track anything about the state of the objects in their pointed-to memory. If an object is moved or copied or destroyed, the pointer will know nothing about it.

A pointer is an address for a location in memory.

It helps to think of pointer-values (addresses) and pointer-variables which contain those values/addresses. Sadly the term pointer has historically had a bit of a double-meaning, to refer both to the pointer-value and the pointer-address, which can seem confusing.

Typically the memory location pointed-by a pointer-variable should contain a valid object within an allocated area of memory, but it also might not.

C++ does not protect you against dangling pointers, where a dangling pointer is a pointer-variable containing an address of an area of memory which has not been allocated to your program.

Neither does C++ protect you against pointers-to un-initialised memory (e.g. if you have allocated memory using malloc but not initialised its contents).

Lastly, C++ does not protect you against memory leaks; you as the programmer are responsible for keeping track of all your allocated memory.

These last 3 points are among some of the many reasons why new/delete tend not to be used very often in modern C++, and why & references, std::vector, std::shared_ptr and other alternatives are preferred; they take care of many nuances and gotchas surrounding new/delete.

Ben Cottrell
  • 5,741
  • 1
  • 27
  • 34