I can't understand why does the following code produce memory leaks (I am using boost::shared_ptr
with static class instance). Could someone help me?
#include <crtdbg.h>
#include <boost/shared_ptr.hpp>
using boost::shared_ptr;
#define _CRTDBG_MAP_ALLOC
#define NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
static struct myclass {
static shared_ptr<int> ptr;
myclass() {
ptr = shared_ptr<int>(NEW int);
}
} myclass_instance;
shared_ptr<int> myclass::ptr;
int main() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF |
_CRTDBG_CHECK_ALWAYS_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
return 0;
}
In Java, the static keyword is primarily used for memory management. We can use the static keyword with variables, methods, blocks, and classes. Using the static class is a way of grouping classes together. It is also used to access the primitive member of the enclosing class through the object reference.
In static class, you are not allowed to create objects. In non-static class, you are allowed to create objects using new keyword. The data members of static class can be directly accessed by its class name. The data members of non-static class is not directly accessed by its class name.
In C# terms, “static” means “relating to the type itself, rather than an instance of the type”. You access a static member using the type name instead of a reference or a value, e.g. Guid. NewGuid(). In addition to methods and variables, you can also declare a class to be static (since C# 2.0).
Use a static class as a unit of organization for methods not associated with particular objects. Also, a static class can make your implementation simpler and faster because you do not have to create an object in order to call its methods.
This is a memory leak. You are initializing a static instance of myclass called myclass_instance. You are also initializing the "shared_ptr myclass::ptr".
According to Stroustrup[3], statics are initialized in the order that they are defined. Therefore you have the static definition of myclass_instance, which initializes the internal ptr on construction. However, you then have the definition of the static myclass::ptr, which invokes the default constructor for shared_ptr.
This is an example of the classic statics ordering problem. The compiler thinks that myclass::ptr wasn't actually initialized, so there's no destruction of the original shared_ptr. Instead, it is just leaked.
You'll need a bare pointer of some kind. If you're using C++11, you can do the Nifty Counter Technique with a ternary assignment statement which does a move to itself if you determine that the object has already been initialized. It's pretty rough, but it works.
Here's how I'd do it in C++11:
#include <crtdbg.h>
#include <memory>
using std;
#define _CRTDBG_MAP_ALLOC
#define NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
// Note that the count could also be a field in an initializer static used in the Nifty Counter
// Technique covered in many texts.
static int count = 0; // This gets implicitly initialized to 0 by the executable load into memory.
static struct myclass {
static shared_ptr<int> ptr;
myclass() {
if (count++ == 0) {
ptr = make_shared<int>(0); //initialization
}
}
} myclass_instance;
shared_ptr<int> myclass::ptr = count == 0 ? make_shared<int>(0) : move(myclass::ptr);
int main() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF |
_CRTDBG_CHECK_ALWAYS_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
return 0;
}
See the following for more information:
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