结合xxx.cpp:(.text+0x55):对‘xxx’未定义的引用剖析Linux环境下动态库.so文件

12 篇文章 1 订阅

操作系统:Linux系统

场景:g++编译,连接动态库文件时


错误示例(中文):

/tmp/cccgNNpb.o:在函数‘main’中:
test.cpp:(.text+0x55):对‘myprint()’未定义的引用


错误示例(英文):

/tmp/cccgNNpb.o: In function 'main':

test.cpp:(.text+0x55):undifined reference to 'myprint()'


分析:命令的格式正确,怎么就会出现未定义的情况?会不会是动态库的问题,因此,先手动写个动态库进行分析

头文件yxjay.h

#ifndef __YXJAY__
#define __YXJAY__

void myprint();

#endif
源码文件yxjay.c

#include <stdio.h>
#include "yxjay.h"
void myprint()
{
	printf("<span>oba没有马</span>\n");
}
测试主函数文件main.c

#include <stdio.h>
#include "yxjay.h"

int main(void)
{	
	
	myprint();
	return 0;
}

编译成动态库文件:

gcc -fPIC -shared yxjay.c -o libyxjay.so
编译主函数,并连接动态库

gcc -o main main.c -L ./ -lyxjay
其中-L为指定动态库路径, ./表示当前路径,也可以用-L.表示连接到当前路径

执行命令./main

发现报以下错误:

./main: error while loading shared libraries: libyxjay.so: cannot open shared object file: No such file or directory
用ldd main查看库依赖关系ldd main

root@yxjay:~/桌面# ldd main
    linux-vdso.so.1 (0x00007fff69961000)
    libyxjay.so => not found
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc42bf18000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fc42c2c3000)


发现动态库libyxjay.so并未加载到内存中。

原因是因为gcc连接动态库又连接到系统目录去了,可以使用以下命令暂时将当前目录加到系统目录中去(当前工作路径/root/桌面,libyxjay.so存放在该目录中),但是重启后就无效

ldconfig /root/桌面
或者将libyxjay.so文件加入系统的库文件目录中,默认搜索路径(/lib或者/usr/lib)以及动态库配置文件(/etc/ld.so.conf)

再次用ldd main查看库连接关系

root@yxjay:~/桌面# ldd main
    linux-vdso.so.1 (0x00007ffe405f7000)
    libyxjay.so => /root/桌面/libyxjay.so (0x00007fb64a5d9000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb64a22e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fb64a7da000)

发现已经能找到libyxjay.so的入口了

执行命令./main也能正确显示出对应的结果

root@yxjay:~/桌面# ./main
oba没有马


前面的库文件是用gcc编译的,链接库时也是用gcc编译,那如果用g++编译连接gcc编译的库,结果如何呢?

用以下命令将main.c改成main.cpp

mv main.c main.cpp

然后用以下命令编译连接

g++ main.cpp -o main -L. -lyxjay

问题出现了:

root@yxjay:~/桌面# g++ main.c -o main -L. -lyxjay
/tmp/ccc4AcJv.o:在函数‘main’中:
main.c:(.text+0x5):对‘myprint()’未定义的引用
collect2: error: ld returned 1 exit status

居然显示未定义myprint()函数!但是明明已经在库中编译过了!!!

把main.cpp中的引用库文件代码改成extern “C"试试,改动后的代码如下:

#include <stdio.h>
extern "C"{
	#include "yxjay.h"
}
int main(void)
{	
	myprint();
	return 0;
}
再次编译

g++ main.cpp -o main -L. -lyxjay

编译成功,执行命令

root@yxjay:~/桌面# ./main
oba没有马

也能成功执行!


原因分析:gcc和g++分别对应的是C语音的变成和C++的编译,它们两者对函数名的编译方式不同,导致生成的符号也不一样,因此gcc编译的动态库和g++编译的动态库是不能完全等价的!c++调用gcc编译的动态库,头文件加上extern "C"就行,c调用g++编译的动态库??开玩笑吧!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值