Reputation: 49
Issue Description: When using the dlopen(), static variables inside a class are shared across the process. This means that when the shared object is loaded multiple times, it does not have an individual copy of the static variables inside the class. Expectation is each loaded shared object should have individual copy/memory address of static variable how to achieve the same?
Note1: Static variables at the file scope and function scope have separate copies for each shared object loaded, only problem is with the static variable inside the class.
Note2: Also in windows same program works fine i.e static variable inside the class has different memory address.
Note3 : I have tired dlmopen which solves the core issue but added more and more headache.
Note4: Clang compiler is not having this issue with the same code, only in g++ this issue is poped up.
I have attached sample program which is explaining the issue, Step 1 : Run the script_startup.sh (which will compile and place the libraries at proper location) Step 2 : ./main (which will run the program )
libB.so is loaded twice by the Main program and it will call the init_func() of each libraries loaded. When the first library loaded and called the init_func() , it will create Singleton class instance , when second library loaded and called the init_func() below line is already set to true by first loaded library because of that Singleton class instance is not created. but i am expecting below static variable shouldn't be shared across the library loaded.
snippet :
if (getInstance()->isLogInitDone == false)
snippet:
static Singleton* getInstance() {
// Lock the mutex to ensure thread-safety
static Singleton instance ;
return &instance;
}
Program output: ("singleton instance created" message expected to be printed twice )
root@a083cbdb1786:/mnt/hgfs/DUMMY# ./main
static variable inside function works fine 1
Singleton instance created.
Hello from Singleton!
static variable inside function works fine 1
Hello from Singleton!
global static variable which works fine 1
global static variable which works fine 2
static variable inside function works fine 2
Hello from Singleton!
static variable inside function works fine 2
Hello from Singleton!
global static variable which works fine 10
global static variable which works fine 5
Singleton instance destroyed.
libB.cpp
#include <iostream>
#include <fstream>
#include <string>
static int val_global=0;
static void func_check()
{
static int instance=0;
instance += 1;
std::cout << "static variable inside function works fine "<< instance << std::endl;
}
class Singleton {
private:
Singleton() {
std::cout << "Singleton instance created.\n";
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static bool isLogInitDone;
// Public method to get the instance of the Singleton class
static Singleton* getInstance() {
// Lock the mutex to ensure thread-safety
static Singleton instance ;
return &instance;
}
void showMessage() {
std::cout << "Hello from Singleton!\n";
}
~Singleton() {
std::cout << "Singleton instance destroyed.\n";
}
static void InitLoggingForBusConnector()
{
if (getInstance()->isLogInitDone == false)
{
std::ifstream file("params.ini");
std::cout << "bool varaible value " << getInstance()->isLogInitDone << std::endl;
getInstance()->isLogInitDone=true;
}
}
};
bool Singleton::isLogInitDone = false;
extern "C" {
void print_message() {
std::cout << "global static variable which works fine "<< val_global << std::endl;
}
void init_func(int val)
{
func_check();
val_global=val;
//Singleton::InitLoggingForBusConnector();
Singleton* singleton = Singleton::getInstance();
singleton->showMessage();
//Singleton* anotherSingleton = Singleton::getInstance();
//anotherSingleton->showMessage();
}
}
// .so first 1 , 1
Main.cpp
#include <iostream>
#include <dlfcn.h>
#include <link.h>
/*
g++ -fPIC -shared libB.cpp -o libB.so ; g++ Main.cpp -ldl -o main
cp libB.so LIB2/. ; cp libB.so LIB1/.
./main
*/
int load_libraries_dlopen()
{
// Load libA
void* handleA = dlopen("./LIB1/libB.so", RTLD_NOW | RTLD_LOCAL );
void* handleB;
if (!handleA) {
std::cerr << "Failed to load libA: " << dlerror() << std::endl;
return EXIT_FAILURE;
}
// Get the print_message function from libA
void (*print_message_A)() = (void (*)())dlsym(handleA, "print_message");
if (!print_message_A) {
std::cerr << "Failed to find print_message in libA: " << dlerror() << std::endl;
dlclose(handleA);
dlclose(handleB);
return EXIT_FAILURE;
}
// Get the print_message function from libA
void (*init_func_A)(int) = (void (*)(int))dlsym(handleA, "init_func");
if (!init_func_A) {
std::cerr << "Failed to find print_message in libA: " << dlerror() << std::endl;
dlclose(handleA);
dlclose(handleB);
return EXIT_FAILURE;
}
// Load libB
handleB = dlopen("./LIB2/libB.so", RTLD_NOW | RTLD_LOCAL );
if (!handleB) {
std::cerr << "Failed to load libB: " << dlerror() << std::endl;
dlclose(handleA); // Cleanup before exiting
return EXIT_FAILURE;
}
// Get the print_message function from libB
void (*print_message_B)() = (void (*)())dlsym(handleB, "print_message");
if (!print_message_B) {
std::cerr << "Failed to find print_message in libB: " << dlerror() << std::endl;
dlclose(handleA);
dlclose(handleB);
return EXIT_FAILURE;
}
// Get the print_message function from libA
void (*init_func_B)(int) = (void (*)(int))dlsym(handleB, "init_func");
if (!init_func_B) {
std::cerr << "Failed to find print_message in libA: " << dlerror() << std::endl;
dlclose(handleA);
dlclose(handleB);
return EXIT_FAILURE;
}
init_func_A(1);
init_func_B(2);
// Call the functions
print_message_A(); // Calls function from libA
print_message_B(); // Calls function from libB
init_func_A(10);
init_func_B(5);
// Call the functions
print_message_A(); // Calls function from libA
print_message_B(); // Calls function from libB
// Close the handles (cleanup)
dlclose(handleA);
dlclose(handleB);
return 1;
}
int main() {
load_libraries_dlopen();
return EXIT_SUCCESS;
}
script_startup.sh
mkdir -p LIB2 LIB1
g++ -fPIC -shared libB.cpp -o libB.so
g++ Main.cpp -ldl -o main
cp libB.so LIB2/.
cp libB.so LIB1/.
Upvotes: 4
Views: 89