dlclose 错误:"shared objects still referenced"

Error on dlclose: "shared objects still referenced"

我在 dlclose() 的 .so 上有以下错误:"Shared objects still referenced"。我没有找到太多关于它的信息。你以前有过这样的问题吗?什么样的编程错误(或编译选项?)会导致这种情况?

我唯一尝试的是查看我的模块是否已成功释放所有引用的共享对象,但正如我所见,它们都正常。至少希望如此。我还不能真正使用 LD_DEBUG。

我在 Linux 或开源库中找不到“共享对象仍被引用”错误消息。此消息仅在 QNX 上下文中提及。

这个QT补丁https://qt.gitorious.org/qt/qtbase/commit/4af257eb3cfeef93adefda5f981742ffb58ba0ad说这个错误是提示性的,可以忽略

On QNX that's only "informative"

Shared objects still referenced" dlerror should actually be treated as "for your information" only, not as an actual error.

我们只能通过附加信息来详细说明错误:

(在问题的评论中发布重新讨论。)

以下 可能 在 QNX 上触发 error/warning。我们首先需要两个共享库:

  • shared_needs.c

    /* References a function defined elsewhere. */
    
    void defined_elsewhere(void);
    
    void f(void) {
        defined_elsewhere();
    }
    
  • shared_has.c

    /* Has the function referenced above. */
    
    void defined_elsewhere(void) {}
    

我们按如下方式编译它们(为了简单起见省略了 sonames 和其他良好做法):

$ gcc -shared -fPIC shared_has.c -o shared_has.so
$ gcc -shared -fPIC shared_needs.c -o shared_needs.so

我们现在 load/unload 具有以下代码的库 (loader.c),

#include <dlfcn.h>
#include <stdio.h>

int main(void) {
    void *shared_has;

    /* Pass RTLD_GLOBAL so that defined_elsewhere() becomes
       available to libraries loaded later. */
    shared_has = dlopen("shared_has.so", RTLD_NOW | RTLD_GLOBAL);
    if (shared_has == NULL) {
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    /* shared_needs.so resolves defined_elsewhere() from
       shared_has.so. */    
    if (dlopen("shared_needs.so", RTLD_NOW) == NULL) {
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    /* Might get warning here on QNX, since defined_elsewhere()
       is still used. */
    if (dlclose(shared_has) != 0) {
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    return 0;
}

,我们编译和运行如下:

$ gcc loader.c -ldl -o loader
$ LD_LIBRARY_PATH=. ./loader

以上可能会在 QNX 上打印警告。不过它应该是安全的(因为它在 Linux 上),正如 QNX 上的 dlclose() 手册页所述:

An object won't be removed from the address space until all references to that object (via dlopen() or dependencies from other objects) have been closed.

作为旁注,您可以 运行 objdump -T shared_needs.so 看到 shared_needs.sodefined_elsewhere() 有一个未定义的引用(寻找 **UND**)。