首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么dlsym在动态加载的库中找不到函数?

dlsym 是动态链接库(dynamic linking library)中的一个函数,它用于在运行时查找并获取库中的符号(如函数、变量等)的地址。如果在动态加载的库中使用 dlsym 找不到某个函数,可能有以下几个原因:

基础概念

  • 动态链接库:在程序运行时才加载到内存中的库文件,常见的有 .so 文件(Linux)和 .dll 文件(Windows)。
  • 符号:库中定义的函数、变量等可以被其他程序引用的实体。
  • dlsym:一个标准的库函数,用于在动态链接库中查找符号的地址。

可能的原因及解决方法

  1. 库未正确加载
    • 原因:使用 dlopen 加载库失败,导致后续的 dlsym 调用无法找到任何符号。
    • 解决方法:检查 dlopen 的返回值是否为 NULL,并查看错误信息(通过 dlerror 获取)。
    • 解决方法:检查 dlopen 的返回值是否为 NULL,并查看错误信息(通过 dlerror 获取)。
  • 函数名拼写错误
    • 原因:提供的函数名与库中定义的不匹配。
    • 解决方法:仔细检查函数名的拼写,确保完全一致,包括大小写。
    • 解决方法:仔细检查函数名的拼写,确保完全一致,包括大小写。
  • 库版本不匹配
    • 原因:程序依赖的库版本与实际加载的库版本不一致。
    • 解决方法:确认使用的库版本与编译时链接的版本相同,或者更新程序以适应新的库版本。
  • 编译选项问题
    • 原因:库可能未使用 -fPIC(位置无关代码)选项编译,导致在某些平台上无法正确链接。
    • 解决方法:确保库在编译时使用了 -fPIC 选项。
  • 命名空间冲突
    • 原因:函数可能被定义在一个特定的命名空间或类中,直接使用函数名无法找到。
    • 解决方法:如果函数在命名空间中,需要使用完整的限定名来查找。
    • 解决方法:如果函数在命名空间中,需要使用完整的限定名来查找。
  • 链接器优化
    • 原因:链接器可能优化掉了某些符号,尤其是在使用了 -flto(链接时优化)的情况下。
    • 解决方法:调整编译和链接选项,避免过度优化。

应用场景

  • 插件系统:允许程序在运行时加载和使用外部模块。
  • 扩展功能:在不重新编译主程序的情况下增加新功能。
  • 跨平台兼容性:通过动态加载不同平台的库来实现代码的复用。

示例代码

以下是一个简单的示例,展示如何使用 dlopendlsym

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int main() {
    void* handle = dlopen("libexample.so", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "Error: %s\n", dlerror());
        return 1;
    }

    void (*func)() = dlsym(handle, "exampleFunction");
    const char* dlsym_error = dlerror();
    if (dlsym_error) {
        fprintf(stderr, "Error: %s\n", dlsym_error);
        dlclose(handle);
        return 1;
    }

    func();  // 调用找到的函数
    dlclose(handle);
    return 0;
}

通过以上步骤和检查点,通常可以解决 dlsym 找不到函数的问题。如果问题依然存在,建议进一步检查库的编译和链接过程,确保所有步骤都正确无误。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

动态库的制作与两种使用方式你掌握了吗?

前言 在《如何制作属于自己的静态库》中简单介绍了静态库的制作方法,但实际上动态库的使用更为广泛,至于原因,在《静态库和动态库的区别》一文中已有说明。本文介绍动态库的制作方法以及两种使用方式。...其实我们在使用ldd命令查看的时候,就注意到: libtest.so => not found 它并不能找到这个动态库,因为它会默认从系统库的路径去查找这个库,但是我们并没有把这个库放到系统路径下,因此会找不到了...dlsym函数用于从动态库中查找需要使用的函数; dlclose函数用于卸载已加载的动态库; dlerror函数用于打印动态库相关错误。...: 使用dlopen打开动态库 使用dlsym找到需要使用的符号 调用动态库中的函数 dlopen关闭(卸载)动态库 在文本的代码中,用到了函数指针,相关内容可参考《高级指针话题-函数指针》。...本文总结如下: 程序运行时不能脱离动态库 动态库有两种常见使用方式,一种是加载是链接,一种是运行时链接 只要函数声明没有改变,动态库中函数实现的更新不需要重新编译可执行文件

1.5K50
  • 一种Android App在Native层动态加载so库的方案

    为什么在Native层动态加载so库 随着Android App发展的不断变化,App的性能和系统API框架外的功能拓展显得越来越重要。...Native层的so库动态加载的实现 在Native层的C/C++代码环境,so库动态加载是使用dlopen()、dlsym()和dlclose()这三个函数实现的。...这三个函数均在头文件中定义,它们的作用分别是:dlopen()打开一个动态链接库,返回一个动态链接库的句柄;dlsym()根据动态链接库句柄和符号名,返回动态链接库内的符号地址,这个地址既可以是变量指针...解决方法就是在调用方和被加载的so库都静态引用的公共数据定义中,定义一个虚基类作为操作接口。这个类的具体子类在被加载的so库中实现,调用方使用基类指针操作被加载的so库中的子类实例。...至于如何让调用方创建并获取被加载的so库里的子类实例,首先需要在被加载so库里的子类实现中定义两个前缀带有extern "C"的非成员函数,因为在C++中带有extern "C"这个前缀的函数,在符号名生成的处理将跟

    7.5K60

    大疆一面,说说你理解的运行时加载?

    例如,在大型游戏开发中,新增地图、角色技能等扩展内容可以通过动态库在运行时加载,而无需重新编译整个游戏。这不仅加快了开发迭代速度,还显著降低了维护成本。...但瑕不掩瑜,动态库运行时加载技术为软件开发带来了诸多便利,已成为现代软件开发中不可或缺的一部分。 运行时加载常按照如下的套路进行: 打开动态库:通过特定函数依据路径获取动态库的句柄。...解析函数符号:利用库句柄查找并获取动态库中函数或变量的地址,例如 Windows 使用 GetProcAddress,类 Unix 系统使用 dlsym。...加载函数失败:这可能是因为函数名错误、库文件中不存在该函数、函数未导出。需要查看库函数的代码,并结合库文件进行分析。...,确认导出的符号名称和使用的名称是否一致 动态库依赖问题:如果动态库依赖于其他库,而系统找不到这些依赖库,则会导致加载失败。

    6800

    ubuntu gcc编译时对’xxxx’未定义的引用问题

    dso.o:在函数‘dso_load(char const*, char const*)’中: dso.cpp:(.text+0x3c):对‘dlopen’未定义的引用 dso.cpp:(.text+0x4c...但是在链接为可执行文件的时候就必须要具体的实现了。如果错误是未声明的引用,那就是找不到函数的原型,解决办法这里就不细致说了,通常是相关的头文件未包含。...比如上面的例子,是因为缺失了dlopen、dlsym、dlerror、dlclose这些函数的实现,这几个函数是用于加载动态链接库的,编译的时候需要添加-ldl来使用dl库(这是静态库,在系统目录下/usr...但是看上面编译的时候是有添加-ldl选项的,那么为什么不行呢? gcc 依赖顺序问题 这个主要的原因是gcc编译的时候,各个文件依赖顺序的问题。...例如:在main.c中使用了pthread库相关函数,那么编译的时候必须是main.c在前,-lpthread在后。gcc main.c -lpthread -o a.out。

    8.2K20

    如何识别IDA反汇编中动态链接库中的函数

    在使用IDA静态反汇编时,如果正在逆向的文件中有动态链接库函数(比如调用了程序自定义so库中的函数),IDA只会显示一个地址,跟进去会发现是延迟绑定中关于plt的代码,无法知道具体调用了哪个函数,对于逆向起来很是麻烦...),于是通过查阅《程序员的自我修养》动态链接相关内容,找到了识别动态链接库中函数的方法。...ELF文件中存储了导入的所有函数符号信息,在IDAi的mport窗口中可以看到,不过IDA没有自动显示出来这些函数的地址,但在Linux下使用 readelf -sD 文件名| grep 小写地址 查看该文件可以看到地址动态符号的地址...ELF文件中还存储了needed的动态链接库,IDA中写在了该文件的最开始,向上拉窗口可以看到,我们只要从这些so库中找识别出的函数名即可。...使用 grep -rn “函数名” 即可找到调用的哪个库中的哪个函数。 ? 此外,还有这种形式的动态链接调用,再次挖坑做以记录碰到再研究。

    3.2K70

    Linux下库文件制作方法详解

    执行可执行程序 在执行可执行程序时,出现以下错误,说找不到库文件,在继续往下看之前大家想想这是为什么?...因为在动态函数库使用时,会查找/usr/lib、/lib目录下的动态函数库,而此时我们生成的库不在里边。我们可以通过以下方法解决此问题,其实这个问题在上一节中我们提到过,小伙伴可以回看一下。...,默认是从/usr/lib /lib中读取的,所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig 动态加载库 上面共享库的调用属于动态链接方法,此外我们还可以动态加载...动态加载需要用到系统API函数 接口 描述 dlopen 打开对象文件,可被程序访问 dlsym 获取执行了dlopen函数的对象文件中的符号的地址 dlerror 返回上一次出现的错误 dlclose...共享库文件放置与共享库调用时操作一样 结束语 到目前为止,我们详细讲解了Linux下制作静态库、共享库、以及动态加载库,希望通过此文对你在Linux库的认识有所帮助,那么目的就达到了

    2.1K30

    Android 5.0 到 Android 6.0 + 的深坑之一 之 .so 动态库的适配

    现在我用一句话说白它,就是:不同链接方式时,dlopen会打开指定的系统中(手机中)或提供的动态库,并使用 dlsym 获取符号地址,也就是说,如果,在此时的手机中如果找不到,那么就会出问题,一般和 API...除此之外,凡是后面带“_static”的,表示其是一个静态链接的运行时库(运行时库的代码包含在编译后的程序中);而凡是后面带“_shared”的,表示其是一个动态链接的运行时库(运行时库在程序运行时被动态加载进来...主要是两种,静态链接,动态链接:     动态链接,是指在生成可执行文件时不将所有程序用到的函数链接到一个文件,因为有许多函数在操作系统带的dll文件中,当程序运行时直接从操作系统中找。...插件加载形式有:     1)dlopen     2)dlsym     3)dlclose   dlopen打开指定的系统中(手机中)动态库。...并使用 dlsym 获取符号地址,也就是说,如果,在此时的手机中如果找不到,那么就会出问题,一般和 API 有关系。

    2K100

    在ctypes的C共享库中调用Python函数

    概述 ctypes 是Python标准库中提供的外部函数库,可以用来在Python中调用动态链接库或者共享库中的函数,比如将使用大量循环的代码写在C语言中来进行提速,因为Python代码循环实在是太慢了...大致流程是通过 ctypes 来调用C函数,先将Python类型的对象转换为C的类型,在C函数中做完计算,返回结果到Python中。这个过程相对是比较容易的。...现在有个更复杂的情况,我想要在C代码中调用Python中的某些函数来完成C代码的计算,比如在C代码的sort函数中,采用Python中定义的函数来进行大小判断。...这个在Python中定义的函数在 ctypes 中称为回调函数 (callback function)。也就是说需要把Python函数当作变量传给C语言,想想还是有些难度。...然后在Python文件中定义这个回调函数的具体实现,以及调用共享库my_lib.so中定义的foo函数: # file name: ctype_callback_demo.py import ctypes

    37430

    【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取注入的 libbridge.so 动态库中的 load 函数地址 并 通过 远程调用 执行该函数 )

    文章目录 一、dlsym 函数简介 二、获取 目标进程 linker 中的 dlsym 函数地址 三、远程调用 目标进程 linker 中的 dlsym 函数 获取 注入的 libbridge.so 动态库中的...load 函数地址 四、远程调用 目标进程 中的 libbridge.so 动态库中的 load 函数 一、dlsym 函数简介 ---- dlsym 是 Dynamic Library Symbol...远程调用 目标进程 linker 中的 dlsym 函数 获取 注入的 libbridge.so 动态库中的 load 函数地址 ---- 参考 【Android 逆向】Android 进程注入工具开发...动态库的代码 , 在该换行代码中 , 只是调用 dlopen 函数加载了真正的 libnative.so 动态库 , 这个动态库是进行逆向操作的主要的库 , 执行核心逻辑 ; 先远程注入 libbridge.so...动态库 , 然后远程调用 libbridge.so 中的 load 函数 , 将真正的 libnative.so 加载到目标进程中 ; 使用修改寄存器的方法 强行加载 libbridge.so 动态库

    88910

    MacOS平台下@rpath在动态链接库中的应用

    一、背景介绍       公司开发的一个底层库被用在了Mac平台的多个产品中。在开发这个底层库的初期,对于Mac OSX下的Install name 并没有过多的了解。...对于XCode中的install name项也没有进行过多的配置,于是生成动态库文件在应用到各个产品中时都要修改install name才能用。...后来在使用到CUDA库时,偶然发现了@rpath这个东西在CUDA动态库中被广泛使用。于是就好好研究了下@rpath的一些应用场景。 ?...在动态库中基本上不使用这个path.        (2) @loader_path。这个path在之前的应用中用的非常多,可以通过这个path来设置动态库的install path name。...三、使用方法  (1)在XCode中设置   在编译动态链接库文件(*.dylib)时,应当将install name设置为@rpath/library.dylib。 ?

    4.3K100

    golang plugin源码分析

    什么是Go Plugin Golang是静态编译型语言,在编译时就将所有引用的包(库)全部加载打包到最终的可执行程序(或库文件)中,因此并不能在运行时动态加载其他共享库。...Go Plugin提供了这样一种方式,能够让你在运行时动态加载外部功能。go在1.8 支持了这个功能,类似c语言的动态链接库。...为什么用Go Plugin 其实应该问为什么要用Plugin,我觉得原因有很多,比如: 可插拔:有了Plugin,我的程序可以根据需要随时替换其中某些部件而不用修改我的程序; 动态加载的需要:有些模块只有在运行时才能确定...path err:用于记录过程中的err loaded:这个用于防止并发加载同一个库时候用 syms:这个记录的是库中所有的符号和其对应的值(可能是var、func等) Open函数,封装了open函数...:保存加载的动态库 进入函数,一开始是一些字符串的转换。

    99310

    【C 语言】动态库封装与设计 ( 动态库调用环境搭建 | 创建应用 | 拷贝动态库相关文件到源码路径 | 导入头文件 | 配置动态库引用 | 调用动态库中的函数 )

    文章目录 一、在 Visual Studio 2019 中创建 " 控制台应用 " 程序 二、拷贝 xxx.lib、xxx.dll、xxx.h 到源码路径 三、导入 xxx.h 头文件 四、配置动态库引用...五、调用动态库中的函数 一、在 Visual Studio 2019 中创建 " 控制台应用 " 程序 ---- 欢迎界面中 , 选择 " 创建新项目 " , 选择创建 " 控制台应用 " 项目类型...描述文件 xxx.lib , 动态库文件 xxx.dll , 动态库头文件 xxx.h , 拷贝到 项目的源码路径中 , 注意就是主函数源码所在的目录 ; 三、导入 xxx.h 头文件 ---- 在...出现在 源文件 中 ; 将 xxx.h 头文件手动拖动到 " 头文件 " 中 ; 四、配置动态库引用 ---- 右键点击 " 解决方案 " , 在弹出的菜单中 , 选择 " 属性 " , 选择..." 配置属性 -> 链接器 -> 输入 -> 附加依赖项 " 的 " 编辑 " 选项 , 将 xxx.lib 选项 , 拷贝到此处 ; 五、调用动态库中的函数 导入头文件 , 即可调用动态库中的函数

    2.2K30

    静态链接库和动态链接库的区别

    、隐式方式使用动态库在程序中隐式使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。...快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。...1、动态库的构造和析构函数机制在Linux中,提供了一个机制:在加载和卸载动态库时,可以编写一些函数,处理一些相应的事物,我们称这些函数为动态库的构造和析构函数,其代码格式如下:void __attribute...函数dlsym : 取函数执行地址原型为: void *dlsym(void *handle, char *symbol);dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址...函数功能Windows下Linux下打开加载动态链接库LoadLibrarydlopen获取动态链接库中的函数地址GetProcAddressdlsym关闭动态链接库FreeLibrarydlclose

    8.4K21

    理解Janus中的Plugin

    在Linux系统中,动态加载库其实很容易,只要用两个API 就可以了,即 dlopen 和 dlsym 。...* symbol: 指向动态库中的符号,如函数,变量等 * return: 返回在内存中的符号地址 */ void* dlsym(void* handle, const char* symbol...); 其中,dlopen 用于将动态库加载到内存中;dlsym 用于查找被加载到内存中的动态库的函数或变量的地址。...接下来我们再来看看如何使用 dlopen 及 dlsym 将上面生成的库动态库加载到内存中,并调用它的 add() 方法吧。...下面我们来看看Janus 是如何动态加载库的吧。 为了方便Janus专门创建了一个目录用于存放插件。在Janus启动时它会遍历该目录,并将目录中的插件一个个动态加载到内存中。

    1.4K10

    研读《程序员的自我修养—链接、装载与库》

    动态库也需要参与链接的过程,否则找不到该符号的信息; so保存了完整的符号信息,链接器解析符号时会获取这些信息,用于判断一个符号是否为动态符号; .dll、.so 是常见的动态链接库; 共享对象的最终装载地址在编译时是不确定的...dlfcn.h的方法 dlopen打开动态链接库; dlerror返回错误; dlsym获取函数名或者变量名; dlclose关闭动态库; Objective-C的方法 NSClassFromString...结果思考 Xcode工程link设置上的动态库,会在程序启动时加载到内存,即使你没有用到这个库的函数;(测试代码中没有用到BLib动态库的代码,但是启动即加载了BLib) dispatch_after...是为了延迟,模拟动态加载的过程; 动态库ALib在调用的时候再进行了装载,并且c函数和Objective-C方法均可调用;(测试输出中,loadAlib比loadBLib晚了3秒钟) Xcode工程设置的...(库中只有category没有类的时候,即使有-ObjC, 仍然无法加载category) -force_load,必须跟一个静态库的路径,与-all_load不同的是只会完全加载一个库,不影响其他库文件

    1.6K70

    掌握死锁检测:策略和最佳实践

    2.1、dlsym()函数获取共享对象或可执行文件中符号的地址。...>void *dlvsym(void *handle, char *symbol, char *version);// Link with -ldl.描述:函数dlsym()接受dlopen()返回的动态加载共享对象的...如果在指定对象或加载对象时dlopen()自动加载的任何共享对象中找不到该符号,dlsym()将返回NULL。(dlsym()执行的搜索是通过这些共享对象的依赖关系树进行的广度优先搜索。)...搜索将包括可执行文件及其依赖项中的全局符号,以及使用RTLD_GLOBAL标志动态加载的共享对象中的符号。RTLD_NEXT在当前对象之后,按搜索顺序查找所需符号的下一个匹配项。...这允许在另一个共享对象中为函数提供包装,例如,预加载共享对象中的函数定义可以查找并调用另一共享对象中提供的“真实”函数(或者在预加载有多层的情况下,函数的“下一个”定义)。

    16510

    dlsym用法_DLSS模式

    大家好,又见面了,我是你们的朋友全栈君。 dlsym dlsym,dlvsym – 从一个动态链接库或者可执行文件中获取到符号地址。...详解 函数dlsym()的第一个参数是一个指向已经加载的动态目标的句柄,这个句柄可以是dlopen()函数返回的。 其中symbol参数是一个以null结尾的符号名。...返回值是这个符号加载到内存中的地址。如果这个符号 在指定的目标 或者 在由dlopen(3)装载指定的目标时自动装载的其他共享目标中都没有找到,dlsym()返回NULL指针。...这个搜索范围包含可执行文件中的全局符号以及这个可执行文件的依赖项(也就是使用RTLD_GLOBAL标志动态加载的共享目标) RTLD_NEXT 在当前搜索顺序中找,在当前的目标之后,要找的符号下一次出现的地方...这就允许向在另一个共享目标中的函数提供一层封装。这样一来,在一个预先加载的共享目标中定义的函数中,就可以找到并调用在另一个共享目标中的真函数(其实就是一种劫持呢!!!!)。

    99820
    领券