Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange double destructor call when using shared_ptr

Finally I tracked down very strange bug, which is caused by double calling destructor. Here is the minimal code that reproduces the bug:

#include <iostream>
#include <memory>
#include <set>

class cEventSystem {
    public:
        cEventSystem() {
            std::cout << "constructor: " << this << std::endl;
        }
        ~cEventSystem() {
            std::cout << "destructor: " << this << std::endl;
        }
};

class cSubscriber {
    public:
        cSubscriber(cEventSystem& eventSystem) : eventSystem(eventSystem) {}
        virtual ~cSubscriber() {}
        virtual void onEvent() = 0;
    protected:
        cEventSystem& eventSystem;
};

class cTileBrowser: public cSubscriber {
    public:
        cTileBrowser(cEventSystem eventSystem) : cSubscriber(eventSystem) {}
        void onEvent() {}
};

class cGui: public cSubscriber {
    public:
        cGui(cEventSystem& eventSystem) : cSubscriber(eventSystem) {
            tileBrowser = std::make_shared<cTileBrowser>(eventSystem);
        }
        void onEvent() {}
        std::shared_ptr<cTileBrowser> tileBrowser;
};

int main() {
    cEventSystem eventSystem;
    cGui gui(eventSystem);
}

The output is:

 constructor: 0x7fffffffe67f
 destructor: 0x7fffffffe2df
 destructor: 0x7fffffffe67f

As you can see the first destructor is unwanted and it is called on different object which wasn't constructed at all (the adress is different), but in my real code the adress is close enough and it corrupts the containers I have in event system.

Debugging shows that it is make_shared which causes that destructor call.

What causes that unwanted destructor call and how can I get rid of it? I use g++4.7 with c++11 flag.

The problem is that the unwanted destructor call usually (90% of times) corrupts my event system containers in my real code which causes segfaults, but rarely it doesn't corrupt it and everything works.

like image 453
user1873947 Avatar asked Feb 06 '13 23:02

user1873947


1 Answers

The CTileBrowser constructor is taking its argument by value. You're likely seeing the destruction of a temporary copy created for that constructor. Change it to a reference parameter and I bet the problem will go away.

like image 184
Ryan Witmer Avatar answered Sep 27 '22 18:09

Ryan Witmer