dimanche 3 mai 2020

c++11 make_shared

I've been looking into smart pointers, unit testing how they manage memory and am finding and unexpected issue that all the examples recommend doing, but it creates a huge memory leak for me.

This seems to occur when I use a class that has a constructor that builds from another copy of the same class. I'll give an example.

If I have a class like:

Class foo{
public:
    //Ignore unsafe practices here
    HeavyInMemory* variable;

    foo(){
        variable = new HeavyInMemory();
    }

    foo(foo* copyThis){
        variable  = nullptr;
        if(copyThis){
            variable = new HeavyInMemory(copyThis->variable);
        }
    }

    ~foo(){
        delete variable;
    }
}

I find that I will get a huge memory leak because std::make_shared has no way to tell the difference between make_shared(args) and make_shared(new T)

Main(){
    for(int i =0; i < 100; i++{
        //Should not leak, if I follow examples of how to use make_shared
        auto test = make_shared<foo>(new foo());
    }

    //Checking memory addresses these do not match, checking total program memory use, leaks like a 
    //sieve.
}
  • Am I misunderstanding something?
  • Do the examples just not consider this as most use primitive types as examples rather than classes.
  • Does c++11 just not support the make_shared(new T) format even though I see old books like scott meyers books from 1992. It just doesn't make sense.

Also why would you use make_shared(new T) over make_shared(args)? I've seen a couple threads where people have asked this on here, but neither seemed to actually answer the question with a code example.

//As they mainly say code compiler order causes the leak but in my example this would still leak:
auto originalObject = new foo();
auto expectedDestructorWhenOutofScope = make_shared<foo>(originalObject);

//I have found if I give if the object instead it doesn't leak, but this is getting into the realms of
//hacks that may sometimes work
auto originalObject = new foo();
auto expectedDestructorWhenOutofScope = make_shared<foo>(*originalObject);

These two for reference:

Aucun commentaire:

Enregistrer un commentaire