考虑以下循环
while (true) {
void* lib = dlopen("bin/liblibrary.so", RTLD_NOW | RTLD_LOCAL);
assert(lib);
typedef void (*f_t)(void);
f_t f = (f_t)dlsym(lib, "foo");
assert(f);
f();
int res = dlclose(lib);
assert(!res);
}
还有一个包含简单功能的库
extern "C" void foo() {
printf("hello from foo\n");
}
这会在每次迭代时重新加载动态库,或者至少应该如此。
使用 clang 17.0.6 在 Linux (Arch) 上编译它可以按预期工作,并且更改和重新编译库使主二进制文件运行新代码。
但是使用 GCC 14.1.1 的相同标志进行编译不起作用,即使重新加载库,它也会继续调用旧代码。
仅使用
clang++ main.cpp -o main
编译 main,使用 clang++ -shared -fPIC -o liblibrary.so library.cpp
编译库,并使用 GCC 相同的标志,除了 g++
而不是 clang++
。
编辑:进一步测试,当我添加
__attribute__((destructor))
时,它不会被 gCC 调用,但会被 Clang 调用,例如
__attribute__((constructor)) void init_library() {
printf("Library loaded\n");
}
__attribute__((destructor)) void cleanup_library() {
printf("Library unloaded\n");
}
看来这种情况下的问题实际上并不在示例代码中,该示例代码最初是不正确的(使用
assert(!dlclose(lib))
),但不幸的是,这只是示例代码中的问题,而不是我的实际代码中的问题。
这确实让我找到了另一个线程,它暗示了
--no-gnu-unique
,这似乎是使 GCC 实际上卸载库的标志。