动态库编译通过,调用动态库函数运行出现undefined symbol

您所在的位置:网站首页 编译LLD 动态库编译通过,调用动态库函数运行出现undefined symbol

动态库编译通过,调用动态库函数运行出现undefined symbol

2023-08-09 11:34| 来源: 网络整理| 查看: 265

编了一个动态库,写测试程序去调用动态库,程序编译通过,调用动态库里函数出错,通过加上动态库相关依赖库以及 extern“C”声明解决该错误以下,详细说明解决经过:

首先,刚编译好的动态库需要配置好配置文件,测试编译为可执行程序时需要正确的链接动态库,在这些都没问题时,编译通过,运行时报undefined symbol错误时,往下看看,或许能给你解决

1.现象分析:

错误如图:

在这里插入图片描述

这三个函数都是问题动态库里函数,程序调用动态库应该是通过程序的符号表去找到这个函数再去调用,出现undefined symbol错误意味着程序的符号表中找不到这几个符号,我们可以通过 ldd -r ./app 命令看当前可执行程序app的动态库链接是否有问题。

libz.so.1 => /usr/lib64/libz.so.1 (0x00002b1ecf5f3000) 这种情况意味着能找到该动态库

libz.so.1 => not found 这种就是找不到动态库,

出现第二种现象你需要看一下自己的makefile或者动态库配置文件,动态库名字和路劲是否有问题。

接下来我们说一下第一种情况

2.解决方案

(1)找到我们编译动态库的源文件,在编译指令上加上 -Xlinker --unresolved-symbols=ignore-in-shared-libs 参数,重新编译一次,看看是否是动态库在编译时在链接其他库时出现问题导致,如重新编译时出现undefined symbol:xxx,编译时加上xxx的库以及路径等。

(2)找到重新编译好的库,输入一下指令:nm -g libXXX.so,查看该库的符号,找到问题函数,如下:

在这里插入图片描述

至此,我找到了我的问题了,我在编译动态库时使用g++编译,g++编译器会将函数名进行优化,以便实现c++的重载,因为此时我的函数名被优化成如上图所示,所以导致可执行程序运行时找不到对应的符号

解决方法:给外部使用的函数需要加上声明,extern “C” 函数名 ,让编译器编译时以c语言的方式去编译,不要优化该函数名

重新编译一下动态库,nm -r 查看一下,

在这里插入图片描述

重新编译一下可执行程序,nm -r 查看一下,未出现undefined symbol错误;运行一下没有问题。

3.注意:

如果你都是用g++编译,在编译动态库的函数前加了extern “C” ,在编译可执行程序时需要调用该函数,也需要加上extern "C"去声明这个函数,否则俩者的符号还是不一样。

附上nm命令相关:

nm指令是names的简称,通过该指令可以列举文件中的符号。

用法:nm [选项] [文件名称] ,若未输入文件名,则默认作用于当前路径的a.out文件。 选项: -a 只显示调试信息 -A 在每行符号信息前,打印查询的文件名 -C 将低级别的符号名称转换为用户级别的名称,意思是转换为用户较容易理解的形式,如:class::memberfunction形式的信息 -D 显示动态符号信息 -g 只显示外部符号;封装成动态库时,需要被外部调用的函数必须是外部符号,否则无法使用 -n 将符号按地址排序 -r 反向排序 -u 仅显示未定义符号,实测列出了GLIBC中的memset、memcpy等,不清楚具体作用 -V 输出程序版本 nm支持的目标(或者说文件类型):elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 a.out-i386-linux pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big plugin srec symbolsrec verilog tekhex binary ihex 其实差不多就是动态库、静态库、可执行文件

当然在使用中,不使用参数也可以。最早开始使用这个指令,就是为了查询动态库中的函数是否可以被外部调用,即 nm xxxx.so

会显示出很多符号信息,格式为:值(the symbol value)、类型(the symbol type)和名字(the symbol name)如下:

在这里插入图片描述

对于每一个符号来说,如果类型是小写的,表示该符号是local的;如果符号是大写的,表示该符号是global(external)的。

对于我的需求来说,符号类型为"T",则该函数可被外部调用,为"t",则无法外部调用。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3