Singleton Destructors

后端 未结 12 1709
一整个雨季
一整个雨季 2021-01-31 03:55

Should Singleton objects that don\'t use instance/reference counters be considered memory leaks in C++?

Without a counter that calls for explicit deletion of the singlet

相关标签:
12条回答
  • 2021-01-31 04:21

    You should explicitly clean up all your objects. Never rely on the OS to clean up for you.

    Where I usually use a singleton is to encapsulate control of something like a file, hardware resource, etc. If I don't properly clean up that connection- I can easily leak system resources. The next time the application runs, it might fail if the resource is still locked by the previous operation. Another issue could be that any finalization- such as writing a buffer to disk- might not occur if it still exists in a buffer owned by a singleton instance.

    This is not a memory leaking issue- the issue is more that you may be leaking resources like other than memory which may not be as easily recovered.

    0 讨论(0)
  • 2021-01-31 04:22

    In languages like C++ that don't have garbage collection it is best practice to clean up before termination. You can do this with a destructor friend class.

    class Singleton{
    ...
       friend class Singleton_Cleanup;
    };
    class Singleton_Cleanup{
    public:
        ~Singleton_Cleanup(){
             delete Singleton::ptr;
         }
    };
    

    Create the clean up class upon starting the program and then upon exiting the destructor will be called cleaning up the singleton. This may be more verbose than letting it go to the operating system but it follows RAII principles and depending on the resources allocated in your singleton object it might be necessary.

    0 讨论(0)
  • 2021-01-31 04:25

    Any kind of allocation, except those in shared memories, are automatically cleaned up by the operating system when the process terminates. Therefore you should not have to explicitly call the singleton destructor. In other words no leaks...

    Furthermore a typical singleton implementation like the Meyers' Singleton is not only thread safe during the initialization on the first call but also guaranteed to graceful terminate when the application exits (the destructor is invoked).

    Anyway if the application is sent a unix signal (ie: SIGTERM or SIGHUP) the default behavior is to terminate the process without calling the destructors of static allocated objects (singletons). To overcome this issue for these signals it is possible to dispose a handler calling exit, or dispose exit be such handler -- signal(SIGTERM,exit);

    0 讨论(0)
  • 2021-01-31 04:32

    As so often, "it depends". In any operating system worthy of the name, when your process exits, all memory and other resources used locally within the process WILL be released. You simply don't need to worry about that.

    However, if your singleton is allocating resources with a lifetime outside it's own process (maybe a file, a named mutex, or something similar) then you do need to consider the appropriate cleanup.

    RAII will help you here. If you have a scenario like this:

    class Tempfile
    {
    Tempfile() {}; // creates a temporary file 
    virtual ~Tempfile(); // close AND DELETE the temporary file 
    };
    
    Tempfile &singleton()
    {
      static Tempfile t;
      return t;
    }
    

    ...then you can be reassured that your temporary file WILL be closed and deleted however your application exits. However, this is NOT thread-safe, and the order of object deletion may not be what you expect or require.

    however, if your singleton is implemented like THIS

    Tempfile &singleton()
    {
      static Tempfile *t = NULL;
      if (t == NULL)
        t = new Tempfile(); 
      return *t;
    }
    

    ... then you have a different situation. The memory used by your tempfile will be reclaimed, but the file will NOT be deleted because the destructor will not be invoked.

    0 讨论(0)
  • 2021-01-31 04:32

    How are you creating the object?

    If you're using a global variable or static variable, the destructor will be called, assuming the program exits normally.

    For example, the program

    #include <iostream>
    
    class Test
    {
        const char *msg;
    
    public:
    
        Test(const char *msg)
        : msg(msg)
        {}
    
        ~Test()
        {
            std::cout << "In destructor: " << msg << std::endl;
        }
    };
    
    Test globalTest("GlobalTest");
    
    int main(int, char *argv[])
    {
        static Test staticTest("StaticTest");
    
        return 0;
    }
    

    Prints out

    In destructor: StaticTest 
    In destructor: GlobalTest
    
    0 讨论(0)
  • 2021-01-31 04:36

    Each language and environment will differ, though I agree with @Aaron Fisher that a singleton tends to exist for the duration of the process.

    In the example of C++, using a typical singleton idiom:

    Singleton &get_singleton()
    {
       static Singleton singleton;
       return singleton;
    }
    

    the Singleton instance will be constructed the first time the function is called, and the same instance will have it's destructor called during the global static destructor phase at program shutdown.

    0 讨论(0)
提交回复
热议问题