0

I have a Singleton class implemented like this:

class QueueManager : public QObject
{
    Q_OBJECT
public:
    static QueueManager *instance() {
        static QueueManager ins;
        return &ins;
    }

private:
    QueueManager(QObject *parent = 0);
    ~QueueManager() {
        system("touch ./shared/documents/exec.txt");
    }
};

I realized that ~QueueManager() is never called (exec.txt is not created). But, as pointed out in this thread, C++ standard says that the destructor should get called at the end. Why isn't it called in my case?

I'm on BlackBerry 10, using the qcc compiler.

Community
  • 1
  • 1
Andrej Repiský
  • 377
  • 1
  • 5
  • 17
  • _"Why isn't it called in my case?"_ How did you actually test it? Does your program get shutdown at all? – πάντα ῥεῖ Feb 14 '15 at 21:39
  • https://programmers.stackexchange.com/questions/252/when-is-singleton-appropriate – Deduplicator Feb 14 '15 at 21:41
  • I am not sure, but maybe this applies here: If there is a use of a standard library object or function not permitted within signal handlers (18.10) that does not happen before (1.10) completion of destruction of objects with static storage duration and execution of std::atexit registered functions (18.5), the program has undefined behavior. – 4pie0 Feb 14 '15 at 21:44
  • http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – Deduplicator Feb 14 '15 at 21:52
  • @πάνταῥεῖ Why don't you read the post to see how I tested it? – Andrej Repiský Feb 15 '15 at 12:21

2 Answers2

1

It can be affected by how your program terminates.

Calling abort() for example, will terminate the program without leaving the current block, so does not destroy static objects. Termination of a program due to a signal can - depending on system - result in statics not being destroyed.

The obvious solution to those concerns are to only exit a program by returning to main(), and returning from main().

There is a certain amount of bookkeeping needed by the compiler and standard library to ensure statics are destroyed at all. Some older compilers didn't do that particularly well, although that is less likely with a modern compiler. Before C++11, there were no requirements related to construction/destruction of statics in multithreaded code (since there was a basic assumption of no multithreading in the standard).

Rob
  • 1,818
  • 7
  • 12
  • 1
    `exit()` executes the "atexit" chain which includes the list of destructors for static objects. You're thinking of `abort()` or `terminate()`. – Howard Hinnant Feb 14 '15 at 22:10
  • My program is returning from `main()`. I verified this by adding debug printout to `main()`. – Andrej Repiský Feb 14 '15 at 22:21
  • @AndrejRepisky maybe this environment just doesn't destroy static properly and you will have to find another solution. This sort of bug is not uncommon when embedded manufacturers roll their own implementation. – M.M Feb 14 '15 at 22:39
  • Andrej: You're going to need to provide a small and complete sample of code that provides the same symptom. There is probably some interaction (e.g. with other static objects being destructed, particularly if some destructor attempts to terminate the program) in play that you haven't shown. – Rob Feb 14 '15 at 22:39
  • @Rob: since I'm using closed-source BlackBerry classes (like bb::cascades::Application), I don't think we can check all the destructors. I'm not willing to make an effort to prepare the complete sample application because I don't believe we can fix BB10/QNX code. – Andrej Repiský Feb 15 '15 at 12:17
  • I'm not suggesting you check all constructors in closed-source code. You need to ensure objects YOU control are destroyed. If the problem is an embedded environment like Matt McNabb describes, you need to take control of the object lifetime (e.g. construct them in main(), run rest of code, destruct them). – Rob Feb 15 '15 at 12:24
0

This is not really the solution, but a sufficient workaround for my problem. I have put my disposal code to a slot connected to aboutToQuit() -- the following line in the constructor:

connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(onDestroy()));
Andrej Repiský
  • 377
  • 1
  • 5
  • 17