This is a simple singleton:
class Singleton
{
Singleton();
virtual ~Singleton();
Singleton * Singleton::getInstance()
{
static Singleton * instance;
if (!instance) {
instance = new Singleton();
};
return instance;
};
}
When main code calls Singleton::getInstance()->someMethod()
for the first time, isn't the class instantiated twice? Will be there memory leak?
I am asking because Visual Leak Detector detects memory leak on the line with new Singleton()
.
In other word, Singleton doesn't hold the activity context reference by calling the setString() method. Similarly, if the application class(the class extended from Android Application() ) holds a reference of an activity, or a fragment holds a reference of its views, both will cause a memory leak.
By using singletons in your project, you start to create technical debt. Singletons tend to spread like a virus because it's so easy to access them. It's difficult to keep track of where they're used and getting rid of a singleton can be a refactoring nightmare in large or complex projects.
Singletons are references attached to classes, just as classes are global references these are not reached by the garbage collector. In case the Singleton is a complex object, this entire object, in addition to the transitive closure of all its references, will stay in memory throughout the execution.
The true, non monobehaviour singleton can't really be destroyed or reinitialized as the static field is read only. If you need this you have to do the usual singleton approach with a normal private static variable. To force a reinitialization you just add a method "Destroy" which sets the static reference to "null".
When main code calls
Singleton::getInstance()->someMethod()
for the first time, isn't the class instantiated twice?
No. Calling a static member of Singleton
does not instantiate Singleton
, so the only instance of Singleton
to exist here is the one you create with new
. And you only create it once, because once instance
points to it, you never call new
again.
One problem you have here, however, is that you failed to make getInstance
a static member function. I assume this is a typo/oversight since, otherwise, your program would not even compile. In fact, the declaration is ill-formed even as a non-static member. Furthermore, the constructor should be private
to enforce the notion that only getInstance
may instantiate the type.
Will be there memory leak?
Yes, and this is what Leak Detector is reporting. However, it's minimal: the problem is that there is nothing to delete
that singleton instance right before your program shuts down.
Frankly I wouldn't worry about it. This may be one of those rare times that a leak is acceptable, mostly because more than a "leak" it's just a one-time failure to de-allocate on process shutdown.
However, if you get rid of the pointer entirely then you can avoid both problems at the same time, since one of the last things your program does will be to destroy objects of static storage duration:
#include <iostream>
class Singleton
{
public:
~Singleton() { std::cout << "destruction!\n"; }
static Singleton& getInstance()
{
static Singleton instance;
return instance;
}
void foo() { std::cout << "foo!\n"; }
private:
Singleton() { std::cout << "construction!\n"; }
};
int main()
{
Singleton::getInstance().foo();
}
// Output:
// construction!
// foo!
// destruction!
No need even for a pointer!
This has the added benefit that the entire function becomes inherently thread-safe, at least as of C++11.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With