Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ static classes & shared_ptr memory leaks

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;
}
like image 466
Yippie-Ki-Yay Avatar asked Jun 01 '10 09:06

Yippie-Ki-Yay


People also ask

What is the use of static class?

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.

What is the difference between static class and non-static class in C#?

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.

What is C# static?

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).

When should a class be static?

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.


1 Answers

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:

  1. Lakos, J, 1996, Large-Scale C++ Software Design. Section 7.8.1.3, Addison Wesley, Reading, Massachusetts.
  2. Meyers, S, 2005, Effective C++, Third Edition. Item 4: Make sure that objects are initialized before they're used. Addison Wesley, Reading, Massachusetts.
  3. Stroustrup, B, 2000, The C++ Programming Language Special Edition. Section 10.4.9, Addison Wesley, Reading, Massachusetts.
like image 64
Michael Mueller Avatar answered Sep 25 '22 02:09

Michael Mueller