iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >解决动态库的符号冲突
  • 596
分享到

解决动态库的符号冲突

解决动态库的符号冲突 2020-12-02 16:12:21 596人浏览 才女
摘要

一次debug遇到的疑惑某天发现一个程序有点问题,祭上print大法。 一次debug遇到的疑惑 某天发现一个程序有点问题。祭上print大法,在关键的 lib_func() 函数里添加 print 调试信息

解决动态库的符号冲突

一次debug遇到的疑惑某天发现一个程序有点问题,祭上print大法。

图片

一次debug遇到的疑惑

某天发现一个程序有点问题。祭上print大法,在关键的 lib_func() 函数里添加 print 调试信息,重新编译运行。

期望 print 出的信息一点都没有,但是程序确确实实又执行过了 libfunc() ,因为除了添加的调试 print 没有执行,libfunc() 该有的功能都执行了。这真是奇怪了。

程序不会骗人。执行的 libfunc() 肯定不是我们修改后的那个 libfunc() ,一定是别的地方有原版的 lib_func() 被执行了。一番调查,果然如此。为了便于说明,把程序和现象简化说明如下:

程序包含如下代码文件——

main.c # 主程序
plugin.c # 插件程序
lib.c lib.h # 一个库

Makefile如下:

all:main plugin
main:
    cc -o main main.c lib.c -ldl -rdynamic
plugin:
    cc -shared -fPIC -o plugin.so plugin.c lib.c

编译后,生成可执行程序main, 和动态库文件 plugin.so。其中主程序运行的时候,会动态加载插件 plugin.so (调用了 lib.c 里的程序)并执行。

怀疑出问题的地方在lib.c里。修改后的lib.c内容如下,添加了debug字样。

void lib_func() {   
// fprintf(stderr, "%s()
", __func__);
    fprintf(stderr, "debug:%s()
", __func__);
}

因为主程序没问题,就只重新编译了 plugin.so ,重新运行。

期望得到的print的结果是 debug:libfunc() ,实际得到却是 libfunc()

看起来,一个程序里的确有两份 lib_func() 代码。从Makefile可以看出,一份在main程序里,一份在plugin.so里。实际运行的是main里的那份。

事情忽然就有意思了:如果一个程序里包含多个相同的函数,实际执行的是哪一个?

TIPS:可以简单的使用linux的命令 nm <程序文件> 查看程序里有哪些函数

动态库和符号表

尽管程序各不相同,但总有些功能很常见。每个程序都为他们写一遍代码很不划算,于是独立出来成了库,在多个程序之间共享。一个库也可以使用别的库。有两种共享的办法:静态的,动态的。

在编译时,把库的代码复制一份合并到可执行文件里的,是静态库。

在运行时,把库的代码加载一份到内存里的,是动态库。

动态库更节省资源,不用被复制很多次,更新也方便。

负责链接的东西,叫做链接器(linker),负责加载的叫做加载器(loader)。

然而计算机是根据地址来执行的,每条指令执行前都要先确定地址。动态库加载之前,谁都不知道它会被加载到哪里,也就不知道动态库里的指令的地址,只能通过符号(名称)来记录它提供给别人用的函数列表(导出表),以及它期望别人提供给他的函数列表(导入表)。库被加载后,就获得了地址。程序运行前,需要先解析符号表,确定每个符号的实际地址。

我们开头的例子,两个相同名字的 libfunc() ,一个在main程序里,一个在plugin.so里,main先加载,plugin.so使用的 libfunc() 就被解析到了main的 libfunc() 。执行了老的 libfunc() ,而不是我们修改过的带有debug版本。

TIPS:对程序链接和加载有兴趣的同学可以看看 Linkers and Loaders 这本书,非常详细。

和符号有关的编译器选项和环境变量选项

如果条件允许,尽量不要在同一个程序中出现两份代码,出现相同符号的情况,造成冲突。

如果出现了符号冲突一定要解决:如本例中,假设 main 不可变,已经包含了 lib 的代码。plugin.so 可通过 GCc 的 -Wl,-Bsymbolic选项告诉加载器优先使用自己的符号,而不优先用全局的符号。该选项可以解决符号冲突。

TIPS: 如果想观察加载器的工作,可以使用环境变量 LD_DEBUG=all ./main 来执行程序,会获得详细的解析过程。manpage的 ld.so(8) 有更多详细的说明。

最后附上示例用的代码:

➜  sample cat lib.h
#ifndef UNTITLED_LIB_H
#define UNTITLED_LIB_H

void lib_func();

#endif //UNTITLED_LIB_H
➜  sample cat lib.c
#include 
#include "lib.h"

void lib_func() {
    //fprintf(stderr, "%s()
", __func__); 
    fprintf(stderr, "debug:%s()
", __func__);
}
➜  sample cat main.c  
#include 
#include 
#include 
#include "lib.h"

int main() {
    void *handle = dlopen("./plugin.so", RTLD_NOW);
    void (*plugin_func)() = (void (*)()) dlsym(handle, "plugin");
    plugin_func();
    return 0;
}
➜  sample cat plugin.c 
#include "lib.h"

void plugin() {
    lib_func();
}
➜  sample cat Makefile 
all:main plugin

main:
    cc -o main main.c lib.c -ldl -rdynamic
plugin:plugin.c lib.c
    #cc -shared -fPIC -o plugin.so plugin.c lib.c -Wl,-Bsymbolic
    cc -shared -fPIC -o plugin.so plugin.c lib.c

clean:
    rm -f main plugin.so
➜  sample 

(陈国 | 天存信息)

您可能感兴趣的文档:

--结束END--

本文标题: 解决动态库的符号冲突

本文链接: https://www.lsjlt.com/news/8445.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • @Transactional跟@DS动态数据源注解冲突的解决
    目录@Transactional跟@DS动态数据源注解冲突背景@Transactional执行流程解决方法动态数据源切换失败由事务@Transactional注解导致动态数据源切换失...
    99+
    2024-04-02
  • springboot-启动bean冲突的解决
    目录启动bean冲突启动提示bean重复问题先说结论原理启动bean冲突 在一次启动中遇到了bean冲突的问题,提示存在两个名称重复的bean org.springframework...
    99+
    2024-04-02
  • ViewPager2滑动冲突的解决方法
    ViewPager2滑动冲突解决,供大家参考,具体内容如下 本文章对ViewPager2的滑动冲突没有提供完善的解决方案,仅为巩固解决滑动冲突方面的知识 首先看看没有解决滑动冲突时...
    99+
    2024-04-02
  • win101909驱动冲突如何解决
    本文小编为大家详细介绍“win101909驱动冲突如何解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“win101909驱动冲突如何解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。第一种方法 找到桌面上的【...
    99+
    2023-07-01
  • win101903驱动冲突如何解决
    本篇内容主要讲解“win101903驱动冲突如何解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“win101903驱动冲突如何解决”吧!第一种方法:找到桌面上的【此电脑】图标,右键点击。点击之...
    99+
    2023-07-01
  • win10的1903驱动冲突怎么解决
    本篇内容介绍了“win10的1903驱动冲突怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!第一种方法 找到桌面上的【此电脑】图标,右...
    99+
    2023-07-01
  • Android中DrawerLayout+ViewPager滑动冲突的解决方法
    DrawerLayout 是 Android 官方的侧滑菜单控件,而 ViewPager 相信大家都很熟悉了。今天这里就讲一下当在 DrawerLayout 中嵌套 ViewPager 时,要如何解决滑动冲突的问题,效果如下:首先,让我们先...
    99+
    2023-05-31
    android drawerlayout viewpager
  • springBoot启动报错log4j冲突的解决方案
    springBoot启动报错log4j冲突 先上一段报错内容 SLF4J: Class path contains multiple SLF4J bindings. SLF4J: ...
    99+
    2024-04-02
  • git解决冲突的方法
    这篇文章将为大家详细讲解有关git解决冲突的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。git解决冲突的方法:首先在项目目录上点击右键,点击双向红箭头的位置;然后选择需要修改冲突的文件,选择merg...
    99+
    2023-06-06
  • Android中怎么解决嵌套滑动冲突
    本篇文章为大家展示了Android中怎么解决嵌套滑动冲突,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一.会产生滑动冲突的情况那么什么时候会产生滑动冲突呢?比如你有个activity,activit...
    99+
    2023-05-30
    android
  • springBoot启动报错log4j冲突如何解决
    这篇文章主要讲解了“springBoot启动报错log4j冲突如何解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“springBoot启动报错log4j冲突如何解决”吧!springBoo...
    99+
    2023-06-20
  • linux安装依赖库冲突如何解决
    在Linux上,解决依赖库冲突的方法包括以下几种:1. 使用包管理器解决冲突:大多数Linux发行版都提供了自己的包管理器,如apt...
    99+
    2023-09-22
    linux
  • Android之解决RecyclerView与NestedScrollView的滑动冲突方法
    1、解决RecyclerView与NestedScrollView的滑动冲突 问题一:当我们滑动RecyclerView组件时,上方的轮播图并没有进行滑动(NestedScrollView没有滑动,即...
    99+
    2023-09-15
    android java 开发语言
  • 如何解决springboot-启动bean冲突问题
    小编给大家分享一下如何解决springboot-启动bean冲突问题,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!启动bean冲突在一次启动中遇到了bean冲突的问题,提示存在两个名称重复的beanorg.springfr...
    99+
    2023-06-29
  • jQuery 名称冲突的解决方法
    jQuery 使用名为 noConflict() 的方法来解决该问题。 var jq=jQuery.noConflict(),帮助您使用自己的名称(比如 jq)来代替 $ 符号。 示...
    99+
    2022-11-21
    jQuery 名称冲突
  • 怎样采用JSI解决不同类库间的冲突
    怎样采用JSI解决不同类库间的冲突,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。采用JSI解决不同类库间的冲突众所周知, Scriptaculous所依赖的Prototype库...
    99+
    2023-06-03
  • 解决docker与vmware的冲突问题
    1、docker启动问题: 问题解决: 需要开启Hyper-V,(开启方法:控制面板->程序->程序和功能->启动或关闭Windows功能,然后再重新启动电脑) ...
    99+
    2024-04-02
  • 如何解决Jquery库及其他库之间的$命名冲突
    首先我们应该知道,在jquery中,$(美元符号)就是jquery的别名,也就是说使用$和使用jquery是一样的,在很多时候我们命名空间时,正是因为这个$而产生的冲突的发生。比如说...
    99+
    2022-11-15
    Jquery库 命名冲突
  • 解决Maven依赖冲突的方法
    目录背景处理回顾背景 在项目中screw-core依赖时发生了冲突,控制台指出是log4j产生的依赖冲突,导致程序报错无法运行,是一个典型的maven依赖冲突,基于这个问题进行 处理...
    99+
    2023-05-20
    Maven依赖冲突
  • @feignclient名字冲突的解决方案
    目录@feignclient名字冲突经过研究,解决方法如下@FeignClient同一个name,多个配置类解决方案@feignclient名字冲突 在启动springcloud项目...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作