Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shared_from_this throws an exception

Tags:

c++

boost

qt

I am writing Qt-based app with Blender-like functionality.

It consists of a 'framework' which is GUI + plugin system and plugins. Plugins are Qt dlls with objects (e.g. a Sphere, a Box, etc.) that can be basically created and displayed. All those objects, once created, are stored in the framework in some kind of a container structure which holds shared_ptr's to them (so actually the container is pretty much like vector<shared_ptr<INode>>)

What I want is to use shared_from_this() function inside one of plugins. E.g. Here's a sample plugin (code changed for clarity):

class Q_DECL_IMPORT SphereNode: public INode, public Sphere

Where INode is:

class INode: public QObject, public boost::enable_shared_from_this<INode>

,a base class for everything stored in the container. So the problem is that this function:

void SphereNode::update()
{
 foo(shared_from_this());
}

throws a boost::bad_weak_ptr exception.

A couple of notes how this SphereNode is created (a Factory class)

boost::shared_ptr<INode> NodeFactory::createNode(const QString& type, QString tag)
{
...
QPluginLoader loader(filesPlugin_[i]);
boost::shared_ptr<QObject> plugin(loader.instance());
boost::shared_ptr<INode> iNodePlugin = boost::shared_dynamic_cast<INode>(plugin);
return iNodePlugin;
}

Any ideas?

like image 957
Mikhail Avatar asked Jun 25 '26 07:06

Mikhail


1 Answers

Perhaps it is this line:

boost::shared_ptr<INode> iNodePlugin = boost::shared_dynamic_cast<INode>(plugin);

Which should be replaced by:

boost::shared_ptr<INode> iNodePlugin = dynamic_cast<INode*>(loader.instance())->shared_from_this();

Maybe it has something to do with:

boost::shared_ptr<QObject> plugin(loader.instance());

Here plugin takes ownership of the returned instance. However, the Qt documentation states that the instance will be automatically freed by the QPluginLoader upon destruction.

However, this would rather cause a segfault (undefined behavior) than a regular boost::bad_weak_ptr exception.

If you want to prevent this, you can specify a null_deleter that will do nothing when the reference counter reachs 0.


Are you calling shared_from_this() from either a constructor or a destructor (directly or indirectly) ?

If so, there is your problem.

When you're in the constructor, the object is not fully created yet, so having a shared_ptr to it is invalid.

To avoid this issue, you can get your shared_ptr to the object in a factory method (that you already have anyway), when the object was succesfully constructed.

like image 164
ereOn Avatar answered Jun 26 '26 21:06

ereOn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!