Object pointed by boost::shared_ptr in base class is never destroyed - c++

I have a weird problem with boost shared_ptr:
class A
{
A( )
: m_myObjectPtr( new MyObject( ) )
{
}
protected:
boost::shared_ptr<MyObject> m_myObjectPtr; // MyObject class is a simple class with a constructor and destructor
};
class B : A
{
B( )
{
}
void CleanMyObject( )
{
m_myObjectPtr.reset( );
}
};
class MyObject
{
MyObject( )
{
cout << "Constructed MyObject" << endl;
}
~MyObject( )
{
cout << "Destroyed MyObject" << endl;
}
};
My problem is that the destructor of MyObject is never invoked when I call B::CleanMyObject( ). "Destroyed MyObject" is never printed.
I am seeing this on iOS with arm64 build of boost 1_57 built using https://github.com/danoli3/ofxiOSBoost/blob/master/scripts/build-libc%2B%2B.sh
Any ideas?

The obvious answer is that you have multiple shared_ptrs referring to a single object, so resetting one reduces the reference count but doesn't delete the object.
This can happen even if the shared_ptr isn't referenced outside of A and B. If you assign A or B without overloading operator= or copy A or B (e.g., pass by value, return by value) without overloading the copy constructor, then this will result.
There are several ways you could investigate.
You could check boost::shared_ptr::use_count() within your CleanMyObject to see if it's greater than 1.
If you don't want sharing and reference counting, you could replace boost::shared_ptr with std::unique_ptr or boost::scoped_ptr.
If you want to make sure you're not accidentally copying or assigning A or B, you can derive A from boost::noncopyable.

Going by #Josh Kelley's suggestion, using unique_ptr solved the problem for me.
So I diverted my attention to boost::shared_ptr to understand what is the problem. It turns out that building boost for iOS with flags BOOST_AC_USE_PTHREADS and BOOST_SP_USE_PTHREADS was the original reason for the oddity. Based on:
1) Answer by Andy Weinstein: Boost threads: in IOS, thread_info object is being destructed before the thread finishes executing
2) Weakly ordered CPU tutorial (http://preshing.com/20121019/this-is-why-they-call-it-a-weakly-ordered-cpu/)
It was clear that I should be using Spin Lock i.e., BOOST_SP_USE_SPINLOCK flag for building boost.
The problem seems to be fixed after I rebuilt boost with BOOST_SP_USE_SPINLOCK flag.

The following code illustrates a working example. It uses the shared_ptr<T> from std namespace starting in C++11, but you can substitute boost::shared_ptr<T>.
MyObject::~MyObject is invoked in the call to B::CleanMyObject as you are trying to do.
#include <memory>
#include <iostream>
using namespace std;
class MyObject
{
public:
MyObject()
{
cout << "Constructed MyObject" << endl;
}
~MyObject()
{
cout << "Destroyed MyObject" << endl;
}
};
class A
{
protected:
A()
: m_myObjectPtr(new MyObject())
{
}
std::shared_ptr<MyObject> m_myObjectPtr; // MyObject class is a simple class with a constructor and destructor
};
class B : A
{
public:
B()
{
}
void CleanMyObject()
{
m_myObjectPtr.reset();
}
};
int main() {
B b;
b.CleanMyObject();
}

Related

Removing an object from a singleton-managed container upon destruction

I have a Singleton class that manages a container of Items, exposing public functions that allow Items to be added or removed from the container.
class Item;
typedef std::shared_ptr<Item> ItemPtr;
class Singleton
{
public:
static Singleton& Instance()
{
static std::unique_ptr<Singleton> Instance(new Singleton);
return *Instance;
}
void Add(ItemPtr item)
{
mContainer.push_back(item);
}
void Remove(ItemPtr item)
{
for (auto it = mContainer.begin(); it != mContainer.end(); it++)
if (*it == item)
mContainer.erase(it);
}
private:
std::vector<ItemPtr> mContainer;
};
I'd like Item to have the ability to add itself to the Singleton container via an Add() method, and remove itself from the container upon its destruction.
class Item
{
public:
Item() {}
~Item()
{
Singleton::Instance().Remove(ItemPtr(this));
}
void Add()
{
Singleton::Instance().Add(ItemPtr(this));
}
};
When I run the example below, I get a crash on Singleton::Remove(), specifically a EXC_BAD_ACCESS on mContainer.begin().
int main()
{
Item* a = new Item();
Item* b = new Item();
a->Add();
b->Add();
delete a;
delete b;
}
This seems to indicate that mContainer no longer exists. Looking at the call stack, I can also see one of the root call stack frames is the destructor Singleton::~Singleton(), which would explain why mContainer is no longer there.
I've tried a different approach : instead of using std::shared_ptr<Item> I simply used raw pointers (i.e., Item*) with the appropriate substitutions in the code. It worked without problems.
My questions are:
I guess what's happening is that the ownership of the Item objects is only released by the shared_ptr after the destruction of Singleton, which causes the error. Is this correct?
Is it impossible to do what I want to do if the container in Singleton is of shared_ptr<Item>?
If not, how could I do it?
The wisdom of doing this in the first place notwithstanding, what you want can be achieved if you're willing to use, and abide by the restrictions of, std::enabled_shared_from_this. See below:
#include <iostream>
#include <algorithm>
#include <memory>
#include <vector>
struct Item;
typedef std::shared_ptr<Item> ItemPtr;
class Singleton
{
private:
Singleton() {}
public:
static Singleton &Instance()
{
static Singleton s;
return s;
}
void Add(ItemPtr item)
{
mContainer.emplace_back(std::move(item));
}
void Remove(const ItemPtr& item)
{
mContainer.erase(
std::remove(mContainer.begin(), mContainer.end(), item),
mContainer.end());
}
void Clear()
{
mContainer.clear();
}
private:
std::vector<ItemPtr> mContainer;
};
// note derivation. this means you can get a std::shared_ptr<Item>
// via `shared_from_this` , but it also means the object itself
// MUST be an actual shared object to begin with.
struct Item : public std::enable_shared_from_this<Item>
{
void Add()
{
Singleton::Instance().Add(shared_from_this());
}
};
int main()
{
ItemPtr a = std::make_shared<Item>();
ItemPtr b = std::make_shared<Item>();
// add to the singleton container
a->Add();
b->Add();
// report reference count of 'a'
std::cout << "before removal 'a' has " << a.use_count() << " references\n";
Singleton::Instance().Remove(a);
std::cout << "after removal 'a' has " << a.use_count() << " references\n";
}
Output
before removal 'a' has 2 references
after removal 'a' has 1 references
The most important part of this is the creation of a and b in main . Notice they are, in fact, managed by std::shared_ptr enshrouding from inception. This is required for std::enable_shared_from_this to work correctly. The rest is fairly straight forward. The ability to get a reference-bumped std::shared_ptr from within the body of any member of Item is done via the shared_from_this() member provided from the base class std::enable_shared_from_this.
In short, taking this approach will work for you, but at no point can you use shared_from_this() unless the object it is being fired upon is already managed by a std::shared_ptr in the first place. Keep that in mind.

Change the class of an object: possible with std::move?

I know that I cannot mess with the V-Table (in a somewhat sane way) once an object is created. Which means I have to copy an object to change it's type. Does this also hold true with c++11's std::move and friends?
class Base {
public:
virtual int type() = 0;
// more data members I want to avoid to copy
};
class D1 : public Base {
public:
int type() {
return 1;
}
};
class D2 : public D1 {
public:
int type() {
return 2;
}
};
int main()
{
// creating the actual object, type is D1
D1* obj = new D1();
// this is what does not work, I want to "change" the object to D2
D2* obj2 = &std::move<D2>(*obj);
// cast it to obj2 base class
Base* baseObj = static_cast<D1*>(obj2);
// now I want a "2" here
int t = baseObj->type();
printf ("%d\n", t);
}
I do not know the move semantics very well... But is there something I can change a D1 object into D2 (or vice versa) with type safety? (Both classes are virtually the same from the memory layout)
While you cannot change the type of an existing object, you can easily change the dynamic type of a pointer member and achieve the desired effect. This is known as strategy design pattern.
E.g.:
#include <memory>
#include <iostream>
class Host
{
struct Strategy
{
virtual ~Strategy() = default;
virtual int type() const = 0;
};
struct StrategyA : Strategy { int type() const override { return 1; } };
struct StrategyB : Strategy { int type() const override { return 2; } };
std::unique_ptr<Strategy> strategy_;
public:
Host()
: strategy_(new StrategyA)
{}
int type() const { return strategy_->type(); }
void change_strategy(int type) {
switch(type) {
case 1: strategy_.reset(new StrategyA); break;
case 2: strategy_.reset(new StrategyB); break;
default: std::abort();
}
}
};
int main() {
Host host;
std::cout << host.type() << '\n';
host.change_strategy(2);
std::cout << host.type() << '\n';
}
It seems to me you are not familiar with what std::move actually does.
As others have said, std::move doesn't actually move anything. It obtains an xvalue (a variable that has a name, but can have its resources reused or transfered to another object) reference from an lvalue (essentially a named variable), so, std::move is nothing but a cast. It doesn't create any new object. Read more about it here and here.
Still about move semantics topic,
std::move is mostly useful so that you can force rvalue-aware methods to receive and reuse resources in variables that you absolutely know that can have their resources moved.
To get a more indepth insight of this, I'd recommend reading What are move semantics?. For instance, one of its uses is creating an object from a temporary (e.g, objects created inside a function and then returned):
#include <vector>
#include <iostream>
class A {
public:
// A very large resource
std::vector<int> resource;
// Constructs our very large resource
A(): resource(1024, 0) { std::cout << "Default construct" << std::endl; }
// Move (reuses) a very large resource from an instance
A(A && other) : resource(std::move(other.resource)) {
std::cout << "Move construct" << std::endl;
}
};
Now, A's move constructor is only called when the other object is an rvalue (or an xvalue), such as:
A foo(A a) { return a; }
int main() {
A a = foo(A());
return 0
}
In this scenario, before foo() gets called, a temporary A() is created and passed in as argument. foo() returns it, but since it is a temporary , it fits as an rvalue and is passed to the move constructor of A when constructing A a = foo(A()).
Inside the move constructor of A(), std::move(other.resource) is used when constructing another resource to call the move constructor of std::vector so that it can try to use whatever it can from other.resource instead of creating everything from scratch again (and then copying).
But as stated previously, std::move on itself doesn't move anything, but it is there to convey intent to move, help the compiler do the right thing (and other programmers to read it and understand faster what you meant).
So, to answer your question directly, no, there isn't anything that'd let you transform an object into another, other than constructing a new object. If you are sure that you are going to destroy obj (which you are not doing, by the way), you can implement an constructor of D2 that accepts an rvalue of D1:
class D2 {
public:
D2(D1 && d1) : resource(std::move(d1.resource)) { d1.resource = nullptr; }
}
int main() {
D1 * obj = new D1();
D2 * obj2 = new D2(std::move(*obj));
delete obj;
}
There are other things to consider when doing this, though, such as destructors of moved objects and other details. I'd recommend reading more about the subject and also maybe using a different method of achieving what you are doing, such as the Strategy pattern mentioned in another answer.

Creation of objects only in Manager class

I want to create a manager class which shall manage all the created objects of one type. Naturally this class should also create these objects. Therefore the client isn't allowed to create objects by himself, but instead must always use the manager class to do it.
Additionally the client is allowed to define his own classes which will be managed by one Manager.
template<class Type>
class Manager{
//...
Type* createInstance(){
Type* ptr = new Type();
//do sommething
return ptr;
}
};
The problem is: How do I restrict the creation of instances only to the manager class?
One possibility would be to declare the constructor as private and the Manager class as a friend class:
class A{
friend class Manager<A>;
private:
A(){}
~A(){}
};
Since the client is allowed to define own classes he could just declare the constructor public and the manager would still work without any problems. But the client would be able to create instances of those classes without the manager class witnessing it, resulting in bad behaviour/ressource management of the framework.
Is there a way to overcome this problem?
Managers of this sort are usually a bad pattern. The following code sample shows why.
It's the same problem as the one that says all destructors should be virtual. I use Manager to create a B, which derives from A, assign the object into an A* pointer. If it's destroyed as such, it goes through Manager::destroy(), which will probably not end well since it was created via Manager::make()
#include <iostream>
using namespace std;
template<class Type>
class Manager
{
public:
Manager(char *type)
{
mytype = type;
}
Type *make()
{
Type *ptr = new Type();
cout << "in Manager<" << mytype << ">::make() ptr->mytype is " << ptr->mytype << endl;
return ptr;
}
void destroy(Type *ptr)
{
cout << "in Manager<" << mytype << ">::destroy() ptr->mytype is " << ptr->mytype << endl;
delete ptr;
}
private:
char *mytype;
};
class A
{
friend class Manager<A>;
protected:
A()
{
mytype = "A";
cout << "in A()" << endl;
}
virtual ~A()
{
cout << "in ~A() mytype is " << mytype << endl;
}
char *mytype;
};
class B : public A
{
friend class Manager<B>;
protected:
B()
{
mytype = "B";
cout << "in B()" << endl;
}
virtual ~B()
{
cout << "in ~B() mytype is " << mytype << endl;
}
};
int main()
{
Manager<A> ma("A");
Manager<B> mb("B");
B *b = mb.make();
A *a = b;
ma.destroy(a); // This line calls Manager<A>::destroy. It should call Manager<B>::destroy.
return 0;
}
which produces the following as output:
in A()
in B()
in Manager<B>::make() ptr->mytype is B
in Manager<A>::destroy() ptr->mytype is B -- Oops - wrong destroy.
in ~B() mytype is B
in ~A() mytype is B
Which in turn means you can't use inheritance to it's full capability, which really defeats the purpose of using an OO language in the first place.
Depending on why you think you need a manager, there is probably a better solution.
If it's for memory management (unlikely given your original code snippet), overriding new and delete is worth taking a look at.
If it's for keeping track of all instances for processing purposes (e.g. objects in a game that get updated every game tick) then while it's a bit of a mental gearshift, a better solution is to integrate the manager into the class itself, as a set of static member functions and variables. Managers of this sort are almost invariably singletons, so making them static members / functions gets you to the same place semantically.
So you might have:
static set<A *> s_collection;
static void Heartbeat() // in class A
{
// lock s_collection here
for (auto it = s_collection.begin, end = s_collection.end() it != end; ++it)
{
// process *it
}
// unlock s_collection here
}
and then during A::A() you insert this into s_collection, and likewise during A::~A() you erase this.
Just be careful to use suitable synchronization primitives if you're multithreaded since most stl containers are not inherently thread safe.
You could use some variation of the passkey pattern to achieve this:
http://coliru.stacked-crooked.com/a/257860767a74a15e

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

Static members being destroyed while there are still outstanding instances?

I need to access a static data member from a destructor, but on program exit it seems that it cannot be guaranteed to still exist! For some reason, the static members are being destroyed whilst there are still outstanding instances of the class. It's odd because I've never heard the advice "Never access static members from a destructor" before, and yet I think I'd know about such a limitation if it existed.
I'll give a concrete example:
class MyClass {
public:
~MyClass() { m_instances.erase(m_name); }
private:
long m_name;
static std::map<long, MyClass*> m_instances;
};
In another class, I tried the following nasty hack which appeared to work, though when I think about it I don't think it's really a solution at all.
class MyClass {
friend class Switch;
public:
~MyClass() { if (m_alive) m_instances.erase(m_name); }
private:
static bool m_alive;
class Switch {
~Switch() { MyClass::m_alive = false; }
};
static Switch m_switch;
long m_name;
static std::map<long, MyClass*> m_instances;
};
What if an instance of MyClass is destroyed after m_instances but before m_switch?? And even if m_switch dies first, the boolean m_alive might have been "destroyed" and therefore possibly overwritten to 'true' (unlikely, I know).
So can anyone offer a better solution? I expect I am missing something very obvious here.
This is clearly a problem of static destruction order. I would recommend something like the following:
class MyClass {
public:
MyClass() { add_instance(m_name, this); };
~MyClass() { erase_instance(m_name); }
private:
long m_name;
static std::map<long, MyClass*>& get_instance_map();
static void add_instance(long aName, MyClass* aObj);
static void erase_instance(long aName);
};
std::map<long, MyClass*>* MyClass::get_instance_map() {
static std::map<long, MyClass*>* p_inst = new std::map<long, MyClass*>();
return p_inst;
};
void MyClass::add_instance(long aName, MyClass* aObj) {
static std::map<long, MyClass*>* p_inst = MyClass::get_instance_map();
p_inst->insert( std::make_pair(aName, aObj) );
};
void MyClass::erase_instance(long aName) {
static std::map<long, MyClass*>* p_inst = MyClass::get_instance_map();
p_inst->erase( aName );
};
If you need the instance map to be deleted, it might not be possible. Otherwise, just use a normal construct-on-first-use idiom. The point here is that the map is a heap-allocated std::map object, and not deleting it just means that it will be flushed away as the OS reclaims the freestore memory which will occur after every other "normal" execution, like a destructor call.
There is no guarantee that static members are destroyed only after all instances of an object of the same class. C++ incorporates no reference counting paradigm (shared_ptr notwithstanding).
When considering lifetime, consider your static members as any other static object. There's really nothing binding them to their containing class other than being in the class's "namespace" (warning: not accurate terminology).
So, if your myClass instances are created statically too, then you need to consider normal static object lifetime rules between them:
Example #1:
#include <iostream>
struct A {
A() { std::cout << "*A "; };
~A() { std::cout << "~A "; };
};
struct B {
B() { std::cout << "*B "; };
~B() { std::cout << "~B "; };
static A a;
};
B t;
A B::a;
int main() {}
// Output: *B *A ~A ~B
As you can see, the static member of B is destroyed before the actual instance of B.
Example #2:
#include <iostream>
struct A {
A() { std::cout << "*A "; };
~A() { std::cout << "~A "; };
};
struct B {
B() { std::cout << "*B "; };
~B() { std::cout << "~B "; };
static A a;
};
A B::a;
B t;
int main() {}
// Output: *A *B ~B ~A
Here the reverse is true. It's a cheap fix for your current issue, but my advice is to avoid static instances altogether; you'll only fall into more static initialisation pitfalls like this down the line... possibly with a future incarnation of the same code!
If you are having these kinds of problems with a static, it must mean that MyClass also has static scope and you can't design code like this with one static accessing the other. It might work and it might not work since you have a problem with the order of destruction.
It's also entirely possible that you have another global (static) causing memory corruption. If this is the case it might mean that overwriting one global might overwrite other near by globals residing in the same memory space, i.e. the static you are having problems with has been corrupted and not deleted.