使用 dlclose 和 dlopen 重新加载动态加载的库适用于 Linux 上的 Clang,但不适用于 GCC

问题描述 投票:0回答:1

考虑以下循环

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");
}
c++ linux dlopen dynamic-loading
1个回答
0
投票

看来这种情况下的问题实际上并不在示例代码中,该示例代码最初是不正确的(使用

assert(!dlclose(lib))
),但不幸的是,这只是示例代码中的问题,而不是我的实际代码中的问题。

这确实让我找到了另一个线程,它暗示了

--no-gnu-unique
,这似乎是使 GCC 实际上卸载库的标志。

© www.soinside.com 2019 - 2025. All rights reserved.