c++ - How to handle static variable sharing in dynamic linking of libraries? - Stack Overflow

I have a requirement in which I have to use a singleton class, acting as a database to store some value

I have a requirement in which I have to use a singleton class, acting as a database to store some values. I have also declared a run function in the cpp file of this singleton class in order to change the data and print. Then, I create a shared object of this class using g++ -fPIC -shared -o lib1.so ClassA.cpp. I try to load the library and execute the run function, but a runtime error is generated due to undefined symbol. This is due to the fact that I am not declaring my static variable as nullptr in the implementation of the singleton class, rather I am trying to do it in main. The sole purpose of doing this is keep this singleton object alive in the memory of main process, so that subsequent dynamic libs which are loaded can access the same object. Is there any better way to do this? Here is my current implementation:

// ClassA.h
#ifndef _CLASSA_
#define _CLASSA_


class ClassA{
    private:
        int integer;
        static ClassA* classA;
        ClassA(){}

    public:
        static ClassA* getOrCreate();
        ~ClassA();
        int getInt();
        void setInt(int& a);
};


#endif // _CLASSA_

// ClassA.cpp
#include "ClassA.h"
#include <iostream>

ClassA* ClassA::getOrCreate() {
    if (classA == nullptr) {
        classA = new ClassA();
    }
    return classA;
}

ClassA::~ClassA() {
    delete classA;
}

int ClassA::getInt() {
    return integer;
}

void ClassA::setInt(int& a) {
    integer = a;
}


extern "C" void run() {
    int intin = 42;
    ClassA::getOrCreate()->setInt(intin);
    std::cout << "Value set: " << ClassA::getOrCreate()->getInt() << std::endl;
}

// main.cpp
#include <iostream>
#include <dlfcn.h>
#include "ClassA.h"


ClassA* ClassA::classA = nullptr;
int main() {
    void* handle = dlopen("./lib1.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "Cannot open library: " << dlerror() << std::endl;
        return 1;
    }
    typedef void (*run_func)();
    dlerror();
    run_func run = (run_func) dlsym(handle, "run");
    char* error = dlerror();
    if (error != NULL) {
        fprintf(stderr, "%s\n", error);
        dlclose(handle);
        exit(EXIT_FAILURE);
    }

    run();
    dlclose(handle);
    return 0;
}

I have a requirement in which I have to use a singleton class, acting as a database to store some values. I have also declared a run function in the cpp file of this singleton class in order to change the data and print. Then, I create a shared object of this class using g++ -fPIC -shared -o lib1.so ClassA.cpp. I try to load the library and execute the run function, but a runtime error is generated due to undefined symbol. This is due to the fact that I am not declaring my static variable as nullptr in the implementation of the singleton class, rather I am trying to do it in main. The sole purpose of doing this is keep this singleton object alive in the memory of main process, so that subsequent dynamic libs which are loaded can access the same object. Is there any better way to do this? Here is my current implementation:

// ClassA.h
#ifndef _CLASSA_
#define _CLASSA_


class ClassA{
    private:
        int integer;
        static ClassA* classA;
        ClassA(){}

    public:
        static ClassA* getOrCreate();
        ~ClassA();
        int getInt();
        void setInt(int& a);
};


#endif // _CLASSA_

// ClassA.cpp
#include "ClassA.h"
#include <iostream>

ClassA* ClassA::getOrCreate() {
    if (classA == nullptr) {
        classA = new ClassA();
    }
    return classA;
}

ClassA::~ClassA() {
    delete classA;
}

int ClassA::getInt() {
    return integer;
}

void ClassA::setInt(int& a) {
    integer = a;
}


extern "C" void run() {
    int intin = 42;
    ClassA::getOrCreate()->setInt(intin);
    std::cout << "Value set: " << ClassA::getOrCreate()->getInt() << std::endl;
}

// main.cpp
#include <iostream>
#include <dlfcn.h>
#include "ClassA.h"


ClassA* ClassA::classA = nullptr;
int main() {
    void* handle = dlopen("./lib1.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "Cannot open library: " << dlerror() << std::endl;
        return 1;
    }
    typedef void (*run_func)();
    dlerror();
    run_func run = (run_func) dlsym(handle, "run");
    char* error = dlerror();
    if (error != NULL) {
        fprintf(stderr, "%s\n", error);
        dlclose(handle);
        exit(EXIT_FAILURE);
    }

    run();
    dlclose(handle);
    return 0;
}

Share Improve this question edited Mar 31 at 8:07 Jarod42 219k15 gold badges196 silver badges330 bronze badges asked Mar 31 at 7:54 Tejas SharmaTejas Sharma 1021 silver badge12 bronze badges 13
  • What are you trying to do exactly? Do you need to have the singleton alive even if the library gets unloaded? If that is the case then maybe it would be easier to just static-link that DSO in main (that is, make is a dependency so it gets loaded at program start)? – Andrey Turkin Commented Mar 31 at 8:07
  • @AndreyTurkin, Yes I want the singleton and all the objects pointed by the pointers inside the singleton alive, even if the library gets unloaded, so that the next library can read and write on same data. I can't go with the static linking approach as the libraries linked are based on the user input, and I can't link all the libraries statically. – Tejas Sharma Commented Mar 31 at 8:12
  • Not sure I understand the scenario, but isn't it enough to call getOrCreate() in main and store it in a variable ? – wohlstad Commented Mar 31 at 8:29
  • 2 @TejasSharma why do you have to unload the library in main ? You can keep it loaded for as long as you need the singleton to stay alive. – wohlstad Commented Mar 31 at 8:55
  • 2 Read carefully. .fini is responsible for destruction of objects with static storage duration. It cannot possibly destroy heap allocated objects. It doesn't know where these objects are. – n. m. could be an AI Commented Mar 31 at 17:55
 |  Show 8 more comments

1 Answer 1

Reset to default 1

I want the singleton and all the objects pointed by the pointers inside the singleton alive, even if the library gets unloaded, so that the next library can read and write on same data

Dynamically allocated memory is not affected by dynamic loader but you do need some kind of a "root" pointer to keep a pointer to it. In your implementation it is classA. It can't be a static variable of your library if it gets unloaded since its value would be lost. So your options are limited:

  • don't unload the library, ever (either make it statically-dependent from main executable or dload using RTLD_NODELETE) - you can then use its static memory since it never goes away
  • don't store it in the library - that is your current approach; fairly OK solution if you absolutely must unload that library
  • if you must unload the library and if you really don't want to make that "reverse" dependency and pollute main application with library details then you can make a helper DSO that just holds the singleton pointer (or whatever else you need persisted) and load THAT helper from your library with RTLD_NODELETE

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1743961255a4536724.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信