• undefined symbol 问题解决记录


    历经一个月,昨日完成打印机network部分的编写(c语言),编写makefile构建动态库。构建完成后遂进行调用测试,出现:

    ./network: symbol lookup error: /usr/lib64/netPrnctl.so: undefined symbol: cupsGetDests

    将解决方法与过程记录,以便日后查阅。

    查找与分析原因

    在编译时未出现问题,没有报错,成功编译生成动态库。以下为编译的makefile文件。

    ###########################################################
    #    File:    netPrnctl.so Makefile
    #    Author: Neko
    ###########################################################
    
    CC = gcc
    CFLAGS = -Wall -g -fPIC
    
    INCLUDE = -I./inc -I../ -I../cups -I../backend -I/usr/include/libusb-1.0
    TARGET = netPrnctl.so
    
    vpath % .h ./inc
    
    OBJS    = public.o prnctlAvision.o prnctlNetwork.o prnctl.o
    SRCS    = ./src/public.c ./src/prnctlAvision.c ./src/prnctlNetwork.c ./src/prnctl.c
    
    $(OBJS):$(SRCS)
        $(CC) $(CFLAGS) $(INCLUDE) -c $^
    
    all:$(OBJS)
        $(CC) -shared -fPIC -o $(TARGET) $(OBJS) -pthread
        cp $(TARGET) /usr/bin
        cp $(TARGET) /usr/lib64
    
    clean:
        rm -f *.o
        rm -f netPrnctl.so

    虽成功生成了动态库,但是在调用时却出现找不到符号的问题,于是使用 ldd -r 查看

    neko@neko:~/ZCPrinterDevice/NetworkSetupTool/filter$ ldd -r /usr/lib64/netPrnctl.so
        linux-vdso.so.1 (0x00007ffeef44c000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9607add000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f96076ec000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f9607f0f000)
    undefined symbol: libusb_open    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsArrayNew    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsDirOpen    (/usr/lib64/netPrnctl.so)
    undefined symbol: ppdFindAttr    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsParseOptions    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsGetPPD    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_set_interface_alt_setting    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_release_interface    (/usr/lib64/netPrnctl.so)
    undefined symbol: ppdClose    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsGetOption    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_detach_kernel_driver    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_close    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsFreeOptions    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsDirClose    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_get_string_descriptor_ascii    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_free_config_descriptor    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_get_config_descriptor    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsBackChannelWrite    (/usr/lib64/netPrnctl.so)
    undefined symbol: _cupsGet1284Values    (/usr/lib64/netPrnctl.so)
    undefined symbol: _ppdNormalizeMakeAndModel    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_attach_kernel_driver    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_get_device_list    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_kernel_driver_active    (/usr/lib64/netPrnctl.so)
    undefined symbol: _cups_strcasecmp    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_bulk_transfer    (/usr/lib64/netPrnctl.so)
    undefined symbol: _cupsLangPrintFilter    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsSideChannelRead    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsArrayCount    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsFileClose    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsDirRead    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_set_configuration    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsFreeDests    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_open_device_with_vid_pid    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_reset_device    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_exit    (/usr/lib64/netPrnctl.so)
    undefined symbol: ppdOpenFile    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_init    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_get_device_descriptor    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsBackendReport    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_free_device_list    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_claim_interface    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsFileOpen    (/usr/lib64/netPrnctl.so)
    undefined symbol: libusb_control_transfer    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsFileGets    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsArrayAdd    (/usr/lib64/netPrnctl.so)
    undefined symbol: backendGetMakeModel    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsArrayFind    (/usr/lib64/netPrnctl.so)
    undefined symbol: _cups_strlcpy    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsGetDests    (/usr/lib64/netPrnctl.so)
    undefined symbol: cupsSideChannelWrite    (/usr/lib64/netPrnctl.so)
    undefined symbol: httpAssembleURIf    (/usr/lib64/netPrnctl.so)

    发现动态库没有链接libusb 与 libcups 两个库,所以netPrnctl.so用到的这两个的函数都没有符号。
    虽然构建netPrnctl.so的c文件已包含libusb与cups函数的头文件,编译器做的工作仅是将源文件中以“文本形式”存在的源代码翻译成机器语言(二进制)的形式,并生成目标文件(源代码全部变成"二进制"的形式),在此期间对源代码中的语法进行检查,有语法错误则报错,程序无法通过编译。故编译没有错误仅是说明没有语法上的问题。在实际调用时也可能出现其他情况。
    通过上面的makefile看到,编译生成了

    OBJS = public.o prnctlAvision.o prnctlNetwork.o prnctl.o

    这4个目标文件。
    而当链接器进行链接的时候,会先把各个目标文件在可执行文件(ELF文件的一种,共享库也是属于其中)里面的位置确定下来,然后经过一系列处理,直到把所有目标文件的内容都写在可执行文件中对应的位置上,再经过一些工作,就会生成一个可执行程序。
    由此判断,netPrnctl.so依赖的libusb 与 libcups 两个库没有链接上。

    解决办法

    既然是因为没有链接libusb 与 libcups,那么将这两个库链接上是不是就能解决问题?
    首先查看这两个库的路径。一般gcc里会有。

    neko@neko:~/ZCPrinterDevice/NetworkSetupTool/filter$ ls /usr/lib/x86_64-linux-gnu/ | grep libcups
    libcupscgi.so.1
    libcupsfilters.so.1
    libcupsfilters.so.1.0.0
    libcupsimage.so.2
    libcupsmime.so.1
    libcupsppdc.so.1
    libcups.so.2
    neko@neko:~/ZCPrinterDevice/NetworkSetupTool/filter$ ls /usr/lib/x86_64-linux-gnu/ | grep libusb
    libusb-1.0.a
    libusb-1.0.so
    libusbmuxd.so.4
    libusbmuxd.so.4.0.0

    于是将makefile进行调整,添加链接libusb 与 libcups的语句。

    ###########################################################
    #    File:    netPrnctl.so Makefile
    #    Author: Neko
    ###########################################################
    
    CC = gcc
    CFLAGS = -Wall -g -fPIC
    
    INCLUDE = -I./inc -I../ -I../cups -I../backend -I/usr/include/libusb-1.0
    TARGET = netPrnctl.so
    LIBVAR = -lusb-1.0 -lcups
    LIBPATH = -L/usr/lib64/x86_64-linux-gnu
    
    vpath % .h ./inc
    
    OBJS    = public.o prnctlAvision.o prnctlNetwork.o prnctl.o
    SRCS    = ./src/public.c ./src/prnctlAvision.c ./src/prnctlNetwork.c ./src/prnctl.c
    
    $(OBJS):$(SRCS)
        $(CC) $(CFLAGS) $(INCLUDE) -c $^
    
    all:$(OBJS)
        $(CC) -shared -fPIC -o $(TARGET) $(OBJS) $(LIBPATH) $(LIBVAR) -pthread
        cp $(TARGET) /usr/bin
        cp $(TARGET) /usr/lib64
    
    clean:
        rm -f *.o
        rm -f netPrnctl.so

    编译时却报错

    /usr/bin/ld: 找不到 -lcups

    这里说一下:
    出现 /usr/bin/ld: cannot find(找不到) -lxxx
    xxx表示函式库文件名称,如:libc.so、libltdl.so、libXtst.so。

    命名规则是:lib+库名(即xxx)+.so。

    会发生这样的原因有以下三种情形:

    1 系统没有安装相对应的lib

    2 相对应的lib版本不对

    3 lib(.so档)的symbolic link不正确,没有连结到正确的函式库文件(.so)

    而libcups.so.2不符合命名规则。故报错找不到。
    解决办法:
    到libcups所在路径下,链接新的符合规则的libcups.so

    neko@neko:~/ZCPrinterDevice/NetworkSetupTool/filter$ cd  /usr/lib/x86_64-linux-gnu
    neko@neko:/usr/lib/x86_64-linux-gnu$ sudo ln -s libcups.so.2 libcups.so
    neko@neko:/usr/lib/x86_64-linux-gnu$ cd -
    /home/neko/ZCPrinterDevice/NetworkSetupTool/filter
    neko@neko:~/ZCPrinterDevice/NetworkSetupTool/filter$ ls /usr/lib/x86_64-linux-gnu/ | grep libcups
    libcupscgi.so.1
    libcupsfilters.so.1
    libcupsfilters.so.1.0.0
    libcupsimage.so.2
    libcupsmime.so.1
    libcupsppdc.so.1
    libcups.so
    libcups.so.2

    重新编译成功,没有报错。再次调用测试,也没有出现找不到符号的问题。

    neko@neko:~/ZCPrinterDevice/NetworkSetupTool/filter$ ldd -r /usr/lib64/netPrnctl.so
        linux-vdso.so.1 (0x00007fff43f66000)
        libusb-1.0.so.0 => /lib/x86_64-linux-gnu/libusb-1.0.so.0 (0x00007f4087f39000)
        libcups.so.2 => /usr/lib/x86_64-linux-gnu/libcups.so.2 (0x00007f4087cad000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4087a8e000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f408769d000)
        libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f408747f000)
        libgssapi_krb5.so.2 => /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007f4087234000)
        libgnutls.so.30 => /usr/lib/x86_64-linux-gnu/libgnutls.so.30 (0x00007f4086ecf000)
        libavahi-common.so.3 => /usr/lib/x86_64-linux-gnu/libavahi-common.so.3 (0x00007f4086cc3000)
        libavahi-client.so.3 => /usr/lib/x86_64-linux-gnu/libavahi-client.so.3 (0x00007f4086ab2000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f4086895000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f40864f7000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4088364000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f40862ef000)
        libkrb5.so.3 => /usr/lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007f4086019000)
        libk5crypto.so.3 => /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007f4085de7000)
        libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007f4085be3000)
        libkrb5support.so.0 => /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007f40859d8000)
        libp11-kit.so.0 => /usr/lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007f40856a9000)
        libidn2.so.0 => /usr/lib/x86_64-linux-gnu/libidn2.so.0 (0x00007f408548c000)
        libunistring.so.2 => /usr/lib/x86_64-linux-gnu/libunistring.so.2 (0x00007f408510e000)
        libtasn1.so.6 => /usr/lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007f4084efb000)
        libnettle.so.6 => /usr/lib/x86_64-linux-gnu/libnettle.so.6 (0x00007f4084cc5000)
        libhogweed.so.4 => /usr/lib/x86_64-linux-gnu/libhogweed.so.4 (0x00007f4084a91000)
        libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f4084810000)
        libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007f40845c3000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f40843bf000)
        libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007f40841bb000)
        libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f4083fa0000)
        libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f4083d98000)
        libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007f4083b14000)
        liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f40838ee000)
        liblz4.so.1 => /usr/lib/x86_64-linux-gnu/liblz4.so.1 (0x00007f40836d2000)
        libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f40833b7000)
        libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f40831a2000)
     
    可以看到,依赖的库基本都链接上了。

    结语

    所有错误都有原因,有迹可循。遇到问题不要急躁,静心思考,理出种种可能导致问题的原因,再排除,找到根源去解决。搜索引擎和书籍是很好的工具,凡事先尽量自己想办法,独立解决问题也是一种能力。
    参加工作半年,此时的我也只是一个刚进门的初级工程师。这些话是对我自己的告诫,也是对与我一样在门内探索的同学的建议,希望有所帮助。共勉。

  • 相关阅读:
    [CSP-S模拟测试]:reverse(模拟)
    BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】
    BZOJ2257 [Jsoi2009]瓶子和燃料 【裴蜀定理】
    BZOJ2729 [HNOI2012]排队 【高精 + 组合数学】
    BZOJ1857 [Scoi2010]传送带 【三分法】
    BZOJ2118 墨墨的等式 【最短路】
    BZOJ5340 [Ctsc2018]假面 【概率dp】
    BZOJ5343 [Ctsc2018]混合果汁 【二分 + 主席树】
    BZOJ4869 [Shoi2017]相逢是问候 【扩展欧拉定理 + 线段树】
    BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】
  • 原文地址:https://www.cnblogs.com/NekoCc/p/13489856.html
Copyright © 2020-2023  润新知