0

My instructor says we don't need to delete a singleton object created in the heap because when out of scope its memory is released and auto deletes.

Is it that the compiler treats static objects differently that we don't need to worry about deleting this object from the heap?

In the code below, I think it's the pointer that goes out of scope in main and not the object in the heap itself, but at some point the destructor of the object should be called if indeed the memory is released for this object?

I also tried adding member function DeleteObject in main but I can't see the destructor of the object in heap being called.

but still can't see the destructor show the message on screen.

#include <iostream>
using namespace std;

class Singleton {
public:
static Singleton* GetInstance();
void Show() { cout << "Single object"; }
void DeleteObject();
~Singleton();

private:
static Singleton* psingleton;
Singleton();
};

void Singleton::DeleteObject() {
delete psingleton;
}

Singleton::~Singleton() {
cout << "\n\nAt Destructor";
}

Singleton* Singleton::psingleton = 0;
Singleton::Singleton()
{
//do stuff
}

Singleton* Singleton::GetInstance() {
if (psingleton = NULL ) {
psingleton = new Singleton();
}
return psingleton;
}

int main()
{
Singleton::GetInstance()->Show();
Singleton::GetInstance()->DeleteObject();//another try
return 0;
}

Would expect the object destructor to show a message on screen because it's called.

Sergio Solorzano
  • 476
  • 9
  • 29
  • 2
    Either your professor is wrong, or you misunderstood him. *Sometimes* its ok not to delete a singleton because you would only do so when the program is exitting. When the program exits all memory is going to be freed anyway. – john Feb 08 '19 at 08:18
  • Thank you John, I am being taught (or understood) that when I create an object in the heap, I should delete it, else I can have a leak even if the program ends: memory is not released for these. So I can't understand why in the case of singletons when a program exits the memory allocated to this objects in the heap is released. – Sergio Solorzano Feb 08 '19 at 09:46
  • 1
    You've got that wrong, a computer would very quickly stop working if memory leaks were permanent. All memory (including leaked memory) is returned to the operating system when a program exits. You could have a program which allocated loads of memory, never deleted any of it, but when the program exits everything will get released. It's important to delete memory so that your program doesn't run out of memory *while it's running*. – john Feb 08 '19 at 10:12
  • Thanks a lot @john, definitely not the kind of concept I should be confused about !! Again, thank you so much for your help ! – Sergio Solorzano Feb 08 '19 at 10:24

3 Answers3

3

That's because you have a bug. This here

Singleton* Singleton::GetInstance() {
     if (psingleton = NULL) {
        psingleton = new Singleton();
    }
    return psingleton;
}

Doesn't ever make an object because psingleton = NULL is always casted to false. What you want instead is if (psingleton == NULL) {.

With that fix, the output for me in MSVC is:

Single object

At Destructor

... which is because of the call to Singleton::GetInstance()->DeleteObject();, not because the program has ended.


I think it's the pointer that goes out of scope in main and not the object in the heap itself, but at some point the destructor of the object should be called if indeed the memory is released for this object?

You are correct. The object on the heap does not go out of scope, and no destructor is called just from the program ending.

Blaze
  • 16,736
  • 2
  • 25
  • 44
  • Thank you @blaze and apologies for the bug. If I remove the call to function DeleteObject() I don't see the destructor for Singleton object created in GetInstance() being called yet I read memory for this object is released anyways. If the memory allocated to an object is released, am I right to expect this object to call its destructor? – Sergio Solorzano Feb 08 '19 at 09:40
  • According to the standard (or at least that version of the standard) it should call the destructor. It's not happening for me either, which might have to do with MSVC (the comments in the answer I linked mentioned that MSVC isn't or wasn't following that rule) – Blaze Feb 08 '19 at 09:53
  • Hi @Blaze, I've tested compiling the same code without DeleteObject() function in ubuntu using g++ and the destructor does not show the message on screen either. – Sergio Solorzano Feb 08 '19 at 10:01
  • 1
    @SergioSolorzano never mind, I got something mixed up. The pointer is `static`, but since the singleton object itself isn't, its destructor isn't going to be called just because the program ends. If the singleton object were static, then its destructor would be called when `main` returns, as it is neatly demonstrated here: https://www.geeksforgeeks.org/static-objects-destroyed/ Sorry for the confusion! – Blaze Feb 08 '19 at 10:18
2

My instructor says we don't need to delete a singleton object created in the heap because when out of scope its memory is released and auto deletes.

Is it that the compiler treats static objects differently that we don't need to worry about deleting this object from the heap?

Your instructor is mistaken. A dynamically allocated object (e.g. created with operator new) will only be released if it is specifically destroyed (e.g. using the corresponding operator delete).

It does not matter if the pointer to the object is a static variable.

What does happen, with most modern operating systems, is that the operating system will reclaim memory used by a program as the program terminates (normally or abnormally). However, this does not cause a call of a destructor of a dynamically allocated object. If you rely on the destructor being called (rather than memory being reclaimed) then you need to ensure the destructor is called before the program terminates. For example, if an object manages a system resource, such as a mutex.

The C++ standard does not require dynamically allocated objects to be released as a program terminates. And most (if not all) modern operating systems (unix, windows, etc) that do reclaim memory of exiting processes reclaim memory, will not call destructors of dynamically allocated objects.

There are also operating systems that do not bother to reclaim memory of a terminating program - although usage of such systems is less common now, programs which run on them need to be specifically designed to ensure they correctly release all dynamically allocated objects.

There are, of course, techniques that can be used to ensure that dynamically allocated objects are released (e.g. store the pointer to those objects in a std::unique_ptr). A static std::unique_ptr<T> will be destroyed as the program terminates, and its destructor will automatically destroy any dynamically allocated object it manages. (There are, of course, ways to prevent this happening, such as by calling std::abort()).

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

I think you instructor is mistaken, the code above will cause a memory leak of Singleton objects

newbie
  • 558
  • 7
  • 12
  • 1
    Yes, for example valgrind will report this memory as leaked, and yet this leak will happen right before program termination, so it is not really a problem. – Jędrzej Dudkiewicz Feb 08 '19 at 09:30
  • Hi @JędrzejDudkiewicz does that mean when the program ends, the memory for this object in the heap is released but even if its memory is released its destructor never called? – Sergio Solorzano Feb 08 '19 at 10:05
  • @JędrzejDudkiewicz Thank you for your help in clarifying this for me ! – Sergio Solorzano Feb 08 '19 at 10:25
  • @SergioSolorzano In default case (simply pointer going out of program scope, so memory is lots) destructor won't be executed, BUT system will free memory of whole program (process), so system won't see any leaks. Missing destructor call can be a problem if you want to e.g. delete some temporary files, but when you want your destructor called, you can use any method discussed above. – Jędrzej Dudkiewicz Feb 08 '19 at 11:17