-1

As an example let's talk about singleton implementation using new (the one where you create the actual instance at the first call to getInstance() method instead of using a static field. It dawned on me that it never frees that memory up. But then again it would have to do it right before the application closes so the system will free that memory up anyway.

Aside from bad design, what practical downsides does this approach have?

Edit: Ad comments - all valid points, thanks guys. So let me ask this instead - for a single thread app and POD singleton class are there any practical downsides? Just theoretically, I'm not going to actually do that.

Machavity
  • 30,841
  • 27
  • 92
  • 100
NPS
  • 6,003
  • 11
  • 53
  • 90
  • 3
    It's a bad habit, that's for sure. Other than that it really depends on the operating system. Most major PC operating systems release all resources of a process once the process terminates. And if you use leak-detectors to find memory leaks while running, not freeing memory before process termination will give a false positive. – Some programmer dude Oct 15 '17 at 11:55
  • 3
    Depends if what you have new'd might own external resources not just memory eg. file handles etc. You might want to close these resources nicely instead of just abandoning them. – Richard Critten Oct 15 '17 at 11:56
  • 1
    There is a reason why you should always use the `static` approach for singletons: thread safety (among some others)... – Rakete1111 Oct 15 '17 at 11:58
  • I also recommend you read [Why is Singleton considered an anti-pattern?](https://stackoverflow.com/questions/12755539/why-is-singleton-considered-an-anti-pattern) (and its linked duplicates). – Some programmer dude Oct 15 '17 at 12:08
  • @Rakete1111 Could you elaborate? – NPS Oct 15 '17 at 12:14
  • 1
    @NPS How do you guarantee that `getInstance` is data race free if you use `new`? Using mutexes, sure, but with `static`, you get that for free :) – Rakete1111 Oct 15 '17 at 12:15

2 Answers2

0

for a single thread app and POD singleton class are there any practical downsides? Just theoretically, I'm not going to actually do that.

in standardese

[c++14-Object lifetime-4]For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.

where the dtor is implicitly called on automatic/static variables and such.

So, (assuming a new expression were used to construct the object) the runtime implementation of the invoked allocation function is free to release the memory and let the object decay in oblivion, as long as no observable effects depends on its destruction ( which is trivially true for types with trivial dtors ).

Massimiliano Janes
  • 5,524
  • 1
  • 10
  • 22
  • That doesn't say anything about whether it's OK not to release storage though. – rustyx Oct 15 '17 at 13:16
  • @rustyx if the runtime releases memory upon termination my answer says no ub occurs; if the runtime does not, then what happens is undefined by definition ;) – Massimiliano Janes Oct 15 '17 at 14:04
0

Use a schwartz counter for all singleton types. It's how std::cout is implemented.

Benefits:

  • thread safe

  • correct initialisation order guaranteed when singletons depend on each other

  • correct destruction order at program termination

  • does not use the heap

  • 100% compliant with c++98, c++03, c++11, c++14, c++17...

  • no need for an ugly getInstance() function. Just use the global object.

https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter

As for the headline question:

How bad is not freeing up memory right before the end of program?

Not freeing memory is not so bad when the program is running under an OS which manages process memory.

However, other things that singletons do could include flushing IO buffers (e.g. std::cout, std::cerr). That's probably something you want to avoid losing.

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • How is that thread-safe? https://stackoverflow.com/questions/39393850/can-num-be-atomic-for-int-num – stark Oct 15 '17 at 13:02
  • @stark because all singletons are initialised in the correct order so any dependent threads will find that it has already been initialised. – Richard Hodges Oct 15 '17 at 13:16
  • ok, but sequences of ordered initializations belonging to different TUs can occur concurrently, isn’t it ?... if yes, the reference counter access should still be synchronized – Massimiliano Janes Oct 15 '17 at 14:20
  • @MassimilianoJanes no, they're initialised sequentially, but the sequence of initialisation is unspecified between TUs. The schwartz counter fixes that because it uses uninitialised storage for the counter, which the standard mandates is zero-filled before the initialisation of static objects. Thus when the schwartz-counter's inititaliser is created in any TU, only the first one so initialised will created the singleton. Thus order will always be correct - because any TU which uses the singleton will either find that it's already initialised or will initialise it. – Richard Hodges Oct 15 '17 at 14:53
  • I’m not talking about the relative ordering of initializations, I’m talking about concurrent accesses to the counter during dynamic initialization of different TUs... – Massimiliano Janes Oct 15 '17 at 17:00