在动态加载的 DLL 中声明和初始化的静态成员变量的生命周期
Lifespan of a static member variable declared and initialized in a dynamically loaded DLL
请考虑以下代码示例。我的问题是:Foo::bar 存储在内存中的什么位置? main.cpp编译成的程序的静态存储中是否存在?如果是这样,卸载 myDll.so 时会发生什么情况?
//myDll.hpp
//class definitions
class Bar
{
public:
Bar() = default;
};
class Foo
{
public:
static Bar bar;
};
//declaring free function to be exported
extern "C" Bar* getBar();
//myDll.cpp
#include "myDll.hpp"
//initializing static member variable
Bar Foo::bar;
//definition of exported function
Bar* getBar()
{
return &(Foo::bar);
}
假设把myDll.cpp做成myDll.so是这样的:
g++ -shared -fPIC -o myDll.so myDll.cpp
,它是这样动态加载的:
//main.cpp
void* handle = dlopen( "/path/to/dll/myDll.so", RTLD_NOW);
// do stuff with handle...
dlclose( handle );
调用 dlclose() 时会发生什么? Foo::bar 是否立即超出范围?
是的。 Foo::bar
存在于 myDll.so
的静态存储部分(“.data”段)中,将在 dlclose
之后取消映射。
我能想到两个例外:
- 卸载 DLL 不需要 C 库。一些 C 库(例如,musl)明确记录它们没有操作
dlclose()
- dlopen/dlclose 是引用计数。如果您对同一个库调用
dlopen
两次,则第一次调用 dlopen
不会卸载库。
请考虑以下代码示例。我的问题是:Foo::bar 存储在内存中的什么位置? main.cpp编译成的程序的静态存储中是否存在?如果是这样,卸载 myDll.so 时会发生什么情况?
//myDll.hpp
//class definitions
class Bar
{
public:
Bar() = default;
};
class Foo
{
public:
static Bar bar;
};
//declaring free function to be exported
extern "C" Bar* getBar();
//myDll.cpp
#include "myDll.hpp"
//initializing static member variable
Bar Foo::bar;
//definition of exported function
Bar* getBar()
{
return &(Foo::bar);
}
假设把myDll.cpp做成myDll.so是这样的:
g++ -shared -fPIC -o myDll.so myDll.cpp
,它是这样动态加载的:
//main.cpp
void* handle = dlopen( "/path/to/dll/myDll.so", RTLD_NOW);
// do stuff with handle...
dlclose( handle );
调用 dlclose() 时会发生什么? Foo::bar 是否立即超出范围?
是的。 Foo::bar
存在于 myDll.so
的静态存储部分(“.data”段)中,将在 dlclose
之后取消映射。
我能想到两个例外:
- 卸载 DLL 不需要 C 库。一些 C 库(例如,musl)明确记录它们没有操作
dlclose()
- dlopen/dlclose 是引用计数。如果您对同一个库调用
dlopen
两次,则第一次调用dlopen
不会卸载库。