Linux   发布时间:2022-03-31  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了记录一次采坑--如何处理Linux动态库同名函数?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

一、背景介绍 需求描述:业务提供一个鉴权的静态库,我只需要从url 和 参数中提取相应的参数传给业务的静态库,将静态库的处理结果直接返回给业务(return < 0, 直接返回403)。 但是最近业务反馈,请求部分url直接返回Error:-1015错误,不符合预期。 二、分析过程 业务刚开始反馈问题,我的第一反应:怎么可能是我的问题,我就仅仅写了一个so(暂时命名1.so),直接调用了你们静态库
@H_616_15@
一、背景介绍

需求描述:业务提供一个鉴权的静态库,我只需要从url 和 参数中提取相应的参数传给业务的静态库,将静态库的处理结果直接返回给业务(return < 0,直接返回403)。

但是最近业务反馈,请求部分url直接返回Error:-1015错误,不符合预期。

二、分析过程

业务刚开始反馈问题,我的第一反应怎么可能是我的问题,我就仅仅写了一个so(暂时命名1.so),直接调用了你们静态库,这个-1015不就是你们库返回的结果。 有问题也是业务提供的库有问题。 或者就是业务配置不正确
我临时解决方案:

  1. 让业务检查配置 ,是否和校验级别有关系?
  2. 双方md5的静态库,本地调试结果是否正确?
  3. 上述方案不行: 采用最挫的方案, 既然静态库吐出来的结果,疯狂加printf,我就不信这个邪了

最后还是走到方案3,业务说printf的结果不符合预期,经业务提醒,突然意识到是不是调用链接到其他库的xx_func?

因为项目比较大, 涉及的库比较多,我用nm认真检查了编译时加载的库,竟然还真找到一模一样的接口xx_func

nm   ./lib/liba.a | grep xx_func

@H_618_46@


编译代码的时候,赶紧去掉了同名函数库(因为在makefile文件编译的时候某些公共库认都会编译进去)。重新编译版本。

没有想到,去掉同名函数库,还是存在问题,为什么呢?到底是哪里的问题?

随手直接 nm *.so | grep xx_func,结果在另外一个so(暂时命名2.so)中,发现了同名函数xx_func。 看了一下配置,程序启动的时候首先加载了2.so动态库, 1.so是在2.so后面加载的. 因为优先加载哪个库,就使用哪个库的同名函数,并不会覆盖的情况(自己现网测试 + 测试代码

到这里问题的原因也算是找到了,下面接着就是如何解决问题?

三、解决方

1. 最简单的方案 -- 修改函数名称

因为业务本身提供的静态库,用nm查看函数也不多,为了安全起见,修改每个函数名称增加一些业务私有的东西)。 批量修改函数名可直接使用sed

2. -fvisibility=hidden -- 最安全最推荐的做法

现在C/C++这一块有几十年的历史,该踩的坑大家都应该踩过去了。gcc编译器就直接提供-fvisibility=hidden编译选项,直接让库函数global可见变成local可见, 使用__attribute__((visibility("default")))直接将需要的函数暴漏在外面就行

四、练习实践---验证动态库的同名函数调串

1.代码结构很简单

.  
├── libqqmusic.c              
├── libtmemusic.c              
├── main
├── main.c
├── makefile
└── README.md

2. libqqmusic.c

//libqqmusic.c

#include<stdio.h>

int get_music_id()
{
    return 1111;
}

void qqmusic_print()
{
    printf("qqmusic id: %d\n",get_music_id());

    return;
}

3. libtmemusic.c

//libtmemusic.c

#include<stdio.h>

int get_music_id()
{
    return 2222;
}

void tmemusic_print()
{
    printf("tmemusic id: %d\n",get_music_id());

    return;
}

4. main.c

//main.c

#include<stdio.h>

int main(int argc,char *argv[])
{

    printf("start\n");

    tmemusic_print();

    qqmusic_print();

    tmemusic_print();

    printf("end\n");

    return 0;
}

5.makefile

# 1. create  /etc/ld.so.conf.d/vaynedu-test.conf
#         /usr/lib64/vaynedu
# 2. mkdir /usr/lib64/vaynedu 
#
# 3. \cp *.so /usr/lib64/vaynedu

all:
    gcc -g -fpic -c -o libqqmusic.o libqqmusic.c
    gcc -g -shared -o libqqmusic.so libqqmusic.o 
    gcc -g -fpic -c -o libtmemusic.o libtmemusic.c
    gcc -g -shared -o libtmemusic.so libtmemusic.o
    \cp *.so /usr/lib64/vaynedu
    @ldconfig
    #gcc -g -o main main.c -l. -lqqmusic -ltmemusic
    gcc -g -o main main.c -l. -ltmemusic -lqqmusic
    @echo -e "\n\ncompile complete\n\n"

clean:
    rm -fr *.so *.o

6.测试结果--证明同名函数库受编译时加载顺序的影响

将tmemusic放在前面gcc -g -o main main.c -l. -ltmemusic -lqqmusic

记录一次采坑--如何处理Linux动态库同名函数?


将qqmusic放在前面gcc -g -o main main.c -l. -lqqmusic -ltmemusic

记录一次采坑--如何处理Linux动态库同名函数?

五、总结

《程序的自我修养-链接、装载与库》应该好好的啃一遍,这个一个后台开发必备的知识技能

大佬总结

以上是大佬教程为你收集整理的记录一次采坑--如何处理Linux动态库同名函数?全部内容,希望文章能够帮你解决记录一次采坑--如何处理Linux动态库同名函数?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。