14

我需要在程序的执行周期中使用不同的动态库。看着dlfcn.h我认为这是可能的。我承认没有阅读太多关于动态库加载的文献。

好的,这就是我所做的 -

  • 我创建了名为“libdynamicTest.so.1”的共享库
  • 主APP打开这个solib(dlopen),获取函数指针(dlsym),运行它然后关闭它(dlclose

一切都很好,直到这里。

  • 现在假设我用另一个 libdynamicTest.so.1(一些代码差异)替换我的 libdynamicTest.so.1,我看到了分段错误。此外,我确保在dlclose之后和dlopen之前替换了 solib 。

有人可以解释为什么会出现这种分段错误吗?

我注意到即使我删除 libdynamicTest.so.1 程序仍然执行,安静奇怪。

    SysTrace(("opening dynamic library"));
    handle = dlopen("libdynamicTest.so.1",RTLD_LAZY);
    fn     = dlsym (handle,"dylib_print_msg");
    SysTrace(("Using dynamic library"));
    if(!fn)
    {
        printf("unknown dylib_print_msg..!!\n");
    }
    else
    {
        (*fn)();
    }
    ret = dlclose(handle);
    SysTrace(("closed dynamic library status = [%s]", (ret==0?"OK":"NOK")));

PS 我不是试图修改任何现有程序的行为,也不是构成任何威胁。我正在做一个可行性检查,以将集成测试作为共享库运行。


编辑

我尝试使用 gdb,以下是堆栈跟踪,当故障发生时。

Program received signal SIGSEGV, Segmentation fault.
0x0000003e92408b7b in check_match.8509 () from /lib64/ld-linux-x86-64.so.2
#0  0x0000003e92408b7b in check_match.8509 ()
   from /lib64/ld-linux-x86-64.so.2
#1  0x0000003e92409024 in do_lookup_x () from /lib64/ld-linux-x86-64.so.2
#2  0x0000003e92409222 in _dl_lookup_symbol_x ()
   from /lib64/ld-linux-x86-64.so.2
#3  0x0000003e92908f14 in do_sym () from /lib64/libc.so.6
#4  0x0000003e93001104 in dlsym_doit () from /lib64/libdl.so.2
#5  0x0000003e9240ced6 in _dl_catch_error ()
   from /lib64/ld-linux-x86-64.so.2
#6  0x0000003e9300150d in _dlerror_run () from /lib64/libdl.so.2
#7  0x0000003e930010ba in dlsym () from /lib64/libdl.so.2

编辑

在 svn checkout 共享的代码库http://subversion.assembla.com/svn/dynamic_libso


编辑:- 添加日志 LD_DEBUG=all

32564:     binding file ./test_agent [0] to /lib64/libc.so.6 [0]: normal symbol `__libc_start_main' [GLIBC_2.2.5]
     32564:
     32564:     initialize program: ./test_agent
     32564:
     32564:
     32564:     transferring control: ./test_agent
     32564:
     32564:     symbol=printf;  lookup in file=./test_agent [0]
     32564:     symbol=printf;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     symbol=printf;  lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
     32564:     symbol=printf;  lookup in file=/lib64/libc.so.6 [0]
     32564:     binding file ./test_agent [0] to /lib64/libc.so.6 [0]: normal symbol `printf' [GLIBC_2.2.5]
     32564:     symbol=putchar;  lookup in file=./test_agent [0]
     32564:     symbol=putchar;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     symbol=putchar;  lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
     32564:     symbol=putchar;  lookup in file=/lib64/libc.so.6 [0]
     32564:     binding file ./test_agent [0] to /lib64/libc.so.6 [0]: normal symbol `putchar' [GLIBC_2.2.5]
-hello.c main():20 Msg : hello world ..!!
-hello.c main():24 Msg : opening dynamic library
     32564:     symbol=dlopen;  lookup in file=./test_agent [0]
     32564:     symbol=dlopen;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     binding file ./test_agent [0] to /lib64/libdl.so.2 [0]: normal symbol `dlopen' [GLIBC_2.2.5]
     32564:     opening file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]; direct_opencount=1
     32564:
     32564:     symbol=dlerror;  lookup in file=./test_agent [0]
     32564:     symbol=dlerror;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     binding file ./test_agent [0] to /lib64/libdl.so.2 [0]: normal symbol `dlerror' [GLIBC_2.2.5]
-hello.c main():26 Msg : Opened dynamic library handle = [a16d9000]
     32564:     symbol=dlsym;  lookup in file=./test_agent [0]
     32564:     symbol=dlsym;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     binding file ./test_agent [0] to /lib64/libdl.so.2 [0]: normal symbol `dlsym' [GLIBC_2.2.5]
     32564:     symbol=_dl_sym;  lookup in file=./test_agent [0]
     32564:     symbol=_dl_sym;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     symbol=_dl_sym;  lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
     32564:     symbol=_dl_sym;  lookup in file=/lib64/libc.so.6 [0]
     32564:     binding file /lib64/libdl.so.2 [0] to /lib64/libc.so.6 [0]: normal symbol `_dl_sym' [GLIBC_PRIVATE]
     32564:     symbol=solib_print_msg;  lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
     32564:     binding file /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0] to /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]: normal symbol `solib_print_msg'
-hello.c main():28 Msg : Using dynamic library
     32564:     symbol=printf;  lookup in file=./test_agent [0]
     32564:     symbol=printf;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     symbol=printf;  lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
     32564:     symbol=printf;  lookup in file=/lib64/libc.so.6 [0]
     32564:     binding file /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0] to /lib64/libc.so.6 [0]: normal symbol `printf' [GLIBC_2.2.5]
     32564:     symbol=putchar;  lookup in file=./test_agent [0]
     32564:     symbol=putchar;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     symbol=putchar;  lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
     32564:     symbol=putchar;  lookup in file=/lib64/libc.so.6 [0]
     32564:     binding file /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0] to /lib64/libc.so.6 [0]: normal symbol `putchar' [GLIBC_2.2.5]
-dynamic.c solib_print_msg():9 Msg : nice nice..!!
     32564:     symbol=dlclose;  lookup in file=./test_agent [0]
     32564:     symbol=dlclose;  lookup in file=/lib64/libdl.so.2 [0]
     32564:     binding file ./test_agent [0] to /lib64/libdl.so.2 [0]: normal symbol `dlclose' [GLIBC_2.2.5]
     32564:
     32564:     closing file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1; direct_opencount=0
-hello.c main():40 Msg : closed dynamic library status = [OK]
-hello.c main():24 Msg : opening dynamic library
     32564:     opening file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]; direct_opencount=1
     32564:
-hello.c main():26 Msg : Opened dynamic library handle = [0]
     32564:     symbol=solib_print_msg;  lookup in file=/user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]
     32564:     binding file /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0] to /user/skm/coding/fTest/approach/dynamic_library/gravity/contribs/libs/libdynamicTest.so.1 [0]: normal symbol `solib_print_msg'
-hello.c main():28 Msg : Using dynamic library
Segmentation fault
4

2 回答 2

10

来自“人 dlclose”:

The function dlclose() decrements the reference count on the dynamic
library handle handle.  If the reference count drops to zero and
no other loaded libraries use symbols in it, then the dynamic library
is unloaded.

我猜你正在与“没有其他加载的库在其中使用符号”部分发生冲突。

要进行调试,请使用 运行您的程序LD_DEBUG=bindings,并查找以下消息:

binding file <some.so> [0] to libdynamicTest.so.1 [0]: normal symbol `<symbol>'

更新:

你有几个错误:

  1. 您正在test_agent直接libdynamic.so.1 链接
    cc -o test_agent -L. ...-ldl build/test_agent/hello.o libdynamic.so.1

    一旦你完成了这个,你就不能再期望这个库被卸载了

  2. 通过做这个:

    *((int *)handle) = 0;

    您实际上正在破坏动态加载器的状态,会导致后续dlsym给您提供虚假地址,这会导致您SIGSEGV尝试使用它。

一旦你解决了问题 #2,你的程序将不再崩溃,尽管它仍然不会卸载库。要真正让库卸载,您还需要修复问题 #1。

如果您先修复问题 #1,那么问题 #2 将不再破坏动态加载程序。相反,它会损坏堆,您可以使用 Valgrind 轻松观察到这一点。

于 2012-05-03T15:09:05.333 回答
2

根据man 8 ld.so

BUGS
       Currently ld.so has no means of unloading and searching for com‐
       patible or newer version of libraries.

我不是 100% 确定这是相关的,但听起来可能是相关的。

于 2012-05-03T15:05:54.017 回答