[英]Managing heap with dynamically linked libraries
I'm working on a project which should be able to load dynamically linked libraries at runtime through dlopen
. 我正在开发一个项目,该项目应该能够在运行时通过
dlopen
加载动态链接的库。
The core framework is finished and it is indeed working but I have some doubt about how to correctly manage objects allocated on the heap by the libraries. 核心框架已经完成并且确实可以正常工作,但是我对如何正确管理库在堆上分配的对象存有疑问。 The interface to the library has just one method which returns a pointer to an object statically allocated inside the library which is a subtype of a common class with
virtual
methods 库的接口只有一种方法,该方法返回指向库内部静态分配的对象的指针,该对象是带有
virtual
方法的通用类的子类型。
To explain it better I'll provide a stub of how I want it to work: 为了更好地解释它,我将提供一个我希望它如何工作的存根:
// header common to the core and to the libraries
class BaseSetting {
..
}
class DerivedSetting1 : public BaseSetting { .. }
class DerivedSetting2 : public BaseSetting { .. }
class ObjectInterface {
private:
vector<BaseSetting*> settings;
protected:
void registerSetting(Setting *setting) { settings.push_back(setting); }
public:
vector<Setting*> *getSettings() { return &settings; }
}
// library example
class ConcreteObject {
ConcreteObject() {
registerSetting(new ..);
registerSetting(new ..);
}
static ConcreteObject object;
extern "C" ConcreteObject *retrieve() { return &object; }
The main problem here is how I should manage the heap allocated settings of the library? 这里的主要问题是我应该如何管理库的堆分配设置? I need polymorphism so I can't just store concrete objects inside the vector and at the same time I need to switch between libraries when needed, by unloading the current with
dlclose
, and release all the memory associated with them. 我需要多态性,所以我不能只将具体对象存储在向量中,同时需要在需要时通过使用
dlclose
卸载当前电流并释放与它们关联的所有内存在库之间进行切换。 I could use an unique_ptr
but this would complicates things because I'll be able to use them from the core just by getting the raw pointer through get()
which then would break any ownership. 我可以使用
unique_ptr
但这会使事情复杂化,因为我可以通过从get()
获取原始指针来从内核使用它们,这将破坏所有所有权。
Is there a common design pattern to handle such situations? 是否有通用的设计模式来应对这种情况?
The solution isn't really related to dynamic linking - the problem and its solution is the same whether your objects come from a shared library or is part of the main application as derived classes from a base-class. 该解决方案与动态链接并没有真正的联系-问题和解决方案都是相同的,无论您的对象来自共享库还是作为基础类派生类的主要应用程序的一部分。 The only "extra" problem with dynamic libraries is that you obviously can't use
dlclose
while still having active objects created by code that resides in the dynamic library (unless you are 100% sure NOTHING will call any of the code in the DL, of course). 动态库的唯一“额外”问题是,您显然无法使用
dlclose
而仍然具有由动态库中的代码创建的活动对象(除非您100%确定NOTHING将调用DL中的任何代码,当然)。
Your ObjectInterface needs to have a destructor that deletes the elements in settings
, 您的ObjectInterface需要有一个析构函数,用于删除
settings
的元素,
Alternatively, you will need to have a unregisterSetting
that is called somewhere suitable (eg some destructor). 另外,您将需要有一个在适当位置(例如某些析构函数)调用的
unregisterSetting
。
Have a look at the attachment to this . 看一看在连接到这个 。
module.cc
and client.cc
are external objects dynamically loaded into a shared context and collaborating with each other, app.cc
is the associated magic to make it look C++
. module.cc
和client.cc
是动态加载到共享上下文中并相互协作的外部对象, app.cc
是使它看起来像C++
的关联魔术。 The way they are constructed/destructed is what you may find appropriate for your problem. 您可能会发现它们适合于您的问题的构造/破坏方式。
In essence, each pluggable type is supposed to inherit from a common interface bootstrap_ifc
and have two methods with known interface available from the shared library. 从本质上讲,每个可插入类型都应从公共接口
bootstrap_ifc
继承,并具有两个可从共享库获得的具有已知接口的方法。
extern "C" bootstrap_ifc* client_constructor()
{
return new(std::nothrow) client;
}
extern "C" void client_destructor(bootstrap_ifc* obj)
{
delete obj;
}
You can write a singleton which represents your library (you may use singulatiry library for that). 您可以写一个表示您的库的单例(您可以为此使用单库)。 In constructor of this wrapper you will call dlopen and in destructor dlclose + delete all allocated objects.
在该包装的构造函数中,将调用dlopen,在析构函数dlclose中,将删除所有分配的对象。 Or you want something simpler - just implement functions init and destroy and call them in proper order: dlopen -> init -> work with library -> destroy -> dlclose
或者,您想要更简单的方法-只需实现函数init并销毁并按正确的顺序调用它们即可:dlopen-> init->使用库-> destroy-> dlclose
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.