简体   繁体   中英

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 .

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

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

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

Your ObjectInterface needs to have a destructor that deletes the elements in settings ,

Alternatively, you will need to have a unregisterSetting that is called somewhere suitable (eg some destructor).

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

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. Or you want something simpler - just implement functions init and destroy and call them in proper order: dlopen -> init -> work with library -> destroy -> dlclose

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM