关闭

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

标签: linux动态库so
2480人阅读 评论(0) 收藏 举报
分类:

操作系统: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++编译的动态库??开玩笑吧!!


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:144989次
    • 积分:2050
    • 等级:
    • 排名:千里之外
    • 原创:57篇
    • 转载:10篇
    • 译文:13篇
    • 评论:23条
    文章分类
    最新评论