在动态加载的 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 不会卸载库。