dlclose() 不适用于工厂函数和函数中的复杂静态?
dlclose() doesn't work with factory function & complex static in function?
>我正在制作一个简单的插件框架,我希望能够在其中dlopen()共享库(即.plugin),检查和使用提供的任何工厂函数,并最终dlclose()它,不留痕迹。
我的工厂系统很简单,只有一个导出的函数,该函数返回指向公共基类的指针。为了检查插件是否已正确卸载,我有一个静态对象,其析构函数从主程序设置一个布尔值。
这是主要程序:
// dltest.cpp follows. Compile with g++ -std=c++0x dltest.cpp -o dltest -ldl
#include <dlfcn.h>
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
if (argc > 1)
{
void* h = dlopen(argv[1], RTLD_NOW|RTLD_LOCAL);
if (!h)
{
cerr << "ERROR: " << dlerror() << endl;
return 1;
}
bool isFinilized = false;
*(bool**)dlsym(h, "g_finilized") = &isFinilized;
cout << boolalpha << isFinilized << endl;
if (dlclose(h))
{
cerr << "ERROR: " << dlerror() << endl;
return 2;
}
cout << boolalpha << isFinilized << endl;
}
return 0;
}
插件的代码是:
// libempty.cpp follows. Compile with g++ -std=c++0x libempty.cpp -o libempty.so -fPIC -shared
#include <iostream>
#include <vector>
using namespace std;
bool* g_finilized = nullptr;
struct Finilizer
{
~Finilizer()
{
cout << "~Finilizer()" << endl;
if (g_finilized) *g_finilized = true;
}
} g_finilizer;
class Base
{
public:
virtual void init() = 0;
};
class Foo: public Base
{
virtual void init()
{
static const vector<float> ns = { 0.f, 0.75f, 0.67f, 0.87f };
}
};
extern "C" __attribute__ ((visibility ("default"))) Base* newBase() { return new Foo; }
如果执行,则输出为:
false
false
~Finilizer()
这表明对 dlclose() 的调用没有按预期工作,并且在程序退出之前没有卸载库。
但是,如果我们将向量移动到函数外部,则最后 8 行为:
class Foo: public Base
{
virtual void init()
{
}
};
static const vector<float> ns = { 0.f, 0.75f, 0.67f, 0.87f };
extern "C" __attribute__ ((visibility ("default"))) Base* newBase() { return new Foo; }
然后 dlclose() 工作正常,输出为:
false
~Finilizer()
true
如果向量保留在函数中但不导出工厂,则会生成相同的结果:
class Foo: public Base
{
virtual void init()
{
static const vector<float> ns = { 0.f, 0.75f, 0.67f, 0.87f };
}
};
//extern "C" __attribute__ ((visibility ("default"))) Base* newBase() { return new Foo; }
如果向量用 C 数组替换,则发现阳性结果:
class Foo: public Base
{
virtual void init()
{
static const float ns[] = { 0.f, 0.75f, 0.67f, 0.87f };
}
};
extern "C" __attribute__ ((visibility ("default"))) Base* newBase() { return new Foo; }
这是GCC/Linux中的错误吗?是否有任何解决方法,以便在分解类的成员函数中静态声明复杂对象?
正在发生的事情是libempty.so
中有一个STB_GNU_UNIQUE
符号:
readelf -Ws libempty.so | grep _ZGVZN3Foo4initEvE2ns
91: 0000000000203e80 8 OBJECT UNIQUE DEFAULT 25 _ZGVZN3Foo4initEvE2ns
77: 0000000000203e80 8 OBJECT UNIQUE DEFAULT 25 _ZGVZN3Foo4initEvE2ns
问题是STB_GNU_UNIQUE
符号的工作方式非常不直观,并且在dlopen
/dlclose
调用中持续存在。
使用该符号会强制 glibc 在此处将您的库标记为不可卸载。
GNU_UNIQUE
符号还有其他惊喜。如果使用足够新的黄金链接器,则可以禁用带有--no-gnu-unique
标志的GNU_UNIQUE
。
相关文章:
- 函数复杂度分析
- 函数的时间复杂度是多少?
- 如何计算此排序函数的时间复杂度?
- 当 A 在 for 循环中调用函数 B 时,如何计算函数 A 的空间复杂度?
- 如何计算函数的时间复杂度?
- 此print_star函数的运行时复杂度是多少?
- 在确定函数的时间复杂度时需要帮助
- 如何计算函数的搜索复杂度
- 如何在复杂的算法中处理goto函数?
- 函数参数中使用的复杂文字'i'
- 包装一个函数,在 Cython 中返回复杂类型的向量
- 调用C++具有复杂参数和复杂返回类型的函数 C 代码
- 为什么叮当使我的简单阶乘函数过于复杂
- 使用boost :: Math的Gauss-Kronrod正交正交进行复杂函数的集成
- C :如何在复杂模板类中指定线程函数
- 简单构造函数的复杂编译器输出
- GDB 用户定义函数:如何传递复杂参数
- 如何在 boost.process 间共享内存中使用复杂结构"push_back"函数向量
- 计算Armadillo中复杂对称矩阵的有限特征向量的正确函数
- 在 Cython 中使用 c++ 复杂函数