动态库作用举例

1.定义解析

符号地址:

符号地址是指代码中定义的函数、变量或其他标识符的内存地址。在程序编译和链接的过程中,这些符号会被编译器和链接器分配一个具体的内存地址。

每个符号在程序的执行过程中都有一个唯一的地址,用于指示它在内存中的位置。符号的地址由操作系统和链接器负责管理,它在程序运行时将被加载到内存中的相应位置。

符号地址的概念在计算机科学中是与编程和链接密切相关的。每个函数、变量、常量或其他标识符都有一个关联的地址,它表示该标识符在内存中的位置,可以被程序使用来访问和操作相应的数据或执行相应的代码。

在动态链接过程中,符号的地址可能是在程序运行时动态解析和加载的。通过使用函数如
dlsym(),我们可以在运行时获取符号的地址,并根据它来动态调用对应的函数或操作对应的数据。

在总体上,符号地址是指代码中标识符的内存地址,它是程序在运行时与对应数据或代码之间建立联系的重要概念。

dlsym() :

dlsym() 是一个在动态链接库中查找符号地址的函数。它的作用是根据指定的符号名称,在动态链接库中查找该符号的地址,并返回该地址的指针。

dlsym() 函数通常与 dlopen() 函数配合使用,用于在运行时动态加载共享库,并获取库中定义的符号的地址。

使用 dlsym() 函数可以按照以下方式完成符号地址的查找:

void* dlsym(void* handle, const char* symbol);
  • handle 参数是由之前调用 dlopen() 函数返回的共享库句柄,它用于指定要查找的共享库。

  • symbol 参数是一个字符串,表示要查找的符号的名称。
    dlsym() 函数将会在指定的共享库中查找具有指定名称的符号,并返回该符号的地址。如果找不到该符号,dlsym() 将会返回 NULL。

一旦获取到符号的地址,我们可以将其强制转换为相应类型的函数指针,然后通过该函数指针来调用符号所表示的函数。

总而言之,dlsym() 提供了一种在运行时动态查找共享库中符号地址的机制,使得我们可以通过符号名称来获取共享库中定义的符号地址,并在程序中进行相应的动态调用。

共享库作用

比如,许多软件产品在运行时使用共享库来升级压缩包装的 (shrink-wrapped)二进制程序。还有,大多数 Web 服务器都依赖于共享库的动态链接来提供动态内容 。
当使用共享库来升级压缩包装的二进制程序时,下面是一个示例代码:

示例一

示例共享库源代码(upgrade_lib.c)

#include <stdio.h>void upgrade_function()
{printf("Upgrading program functionality...\n");
}

示例程序源代码(main.c):

#include <dlfcn.h>
#include <stdio.h>typedef void (*UpgradeFunction)();int main()
{// 动态加载共享库void* libHandle = dlopen("./libupgrade.so", RTLD_LAZY);if (!libHandle) {fprintf(stderr, "Error: Failed to load upgrade library: %s\n", dlerror());return 1;}// 获取共享库中的函数指针UpgradeFunction upgrade = (UpgradeFunction)dlsym(libHandle, "upgrade_function");if (!upgrade) {fprintf(stderr, "Error: Failed to find upgrade function in the library: %s\n", dlerror());dlclose(libHandle);return 1;}// 执行升级功能upgrade();// 关闭共享库dlclose(libHandle);return 0;
}

在上述代码中,我们定义了一个简单的升级函数 upgrade_function(),它会打印一条升级功能的信息。然后,在主程序中,我们使用 dlopen() 函数动态加载名为 “libupgrade.so” 的共享库,并获取其中的升级函数的函数指针。最后,通过调用该函数指针来执行升级功能。

要使用这个示例代码,需要先编译共享库和主程序。使用以下命令来编译:

# 编译共享库
gcc -shared -o libupgrade.so upgrade_lib.c# 编译主程序
gcc -o my_program main.c -ldl

执行 ./my_program 命令来运行程序,它将加载共享库,调用升级函数,并打印相应的升级信息。

如果要升级功能,只需替换 libupgrade.so 文件,并重新运行程序,它将加载新的共享库并执行新的升级功能。这样可以实现在无需重新编译自身二进制程序的情况下,通过替换共享库来升级程序功能。

UpgradeFunction 是一个用户定义的函数指针类型,用于指向具有特定签名(参数和返回值类型)的函数。

在示例中,我们定义了 typedef void (*UpgradeFunction)();,它表示 UpgradeFunction 是一个函数指针类型,指向一个没有参数并且没有返回值的函数。

dlfcn.h 是一个头文件,它包含了操作系统提供的动态链接库(共享库)相关的函数和宏定义。这些函数和宏定义包括了动态加载共享库、获取符号地址、关闭共享库等操作的声明。

在示例程序中,我们使用 dlopen()、dlsym() 和 dlclose() 函数来操作动态链接库。这些函数都是在 dlfcn.h 头文件中声明的。

通过包含 dlfcn.h 头文件,我们可以在代码中调用这些动态链接库相关的函数,以实现动态加载共享库并获取其中的函数指针,以及在需要时关闭共享库等功能。

在使用 dlsym() 函数获取共享库中的符号地址时,我们将其结果进行强制类型转换为 UpgradeFunction 类型,是为了确保编译器正确解释该地址对应的函数类型。

dlsym() 函数的返回值类型是 void*,即一个指向内存地址的指针。但在我们的示例中,我们定义了 UpgradeFunction 作为一个函数指针类型,用于指向没有参数和返回值的函数。因此,我们需要通过类型强制转换,将 void* 类型的地址转换为 UpgradeFunction 类型的函数指针。

这样做是为了确保编译器正确理解返回的地址是一个函数的地址,并且能够正确处理函数的调用。如果不进行类型转换,编译器可能会给出警告或错误,因为它无法确定返回的地址的类型,并且无法正确验证函数的参数和返回值的匹配情况。

在使用 dlsym() 获取函数指针时,确保强制类型转换的目标类型与实际函数的签名匹配是很重要的。如果类型不匹配,可能导致函数调用时发生错误或未定义的行为。所以,为了确保类型的匹配性和安全性,我们将 dlsym() 的结果转换为 UpgradeFunction 类型。

示例二

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fastapi写一个上传的接口

首先&#xff0c;确保您已经在 Python 环境中安装了 FastAPI。 安装环境&#xff1a; pip install fastapi uvicorn让我们创建一个图片上传的接口&#xff1a; from fastapi import FastAPI, File, UploadFile from fastapi.responses import JSONResponse import shutil im…

Dynamic Wallpaper for Mac:动态壁纸让桌面更生动

Dynamic Wallpaper for Mac是一款为苹果电脑用户精心设计的动态壁纸软件&#xff0c;它以其丰富的功能和精美的壁纸库&#xff0c;为用户带来了更加生动和个性化的桌面体验。 Dynamic Wallpaper for Mac v17.8中文版下载 这款软件支持多种动态壁纸&#xff0c;用户可以根据自己…

AirServer投屏软件

AirServer下载:https://souurl.cn/7xWmKW AirServer是一款功能强大的屏幕镜像接收器&#xff0c;它适用于Mac和PC&#xff0c;允许用户接收来自iOS、Android、Mac和Windows等设备的AirPlay和Google Cast流。这款软件可以让用户将手机或平板电脑的屏幕内容无线投射到电脑上&…

2024.4.19力扣每日一题——准时抵达会议现场的最小跳过休息次数

2024.4.19 题目来源我的题解方法一 动态规划浮点数精度方法二 动态规划不考虑浮点数精度问题 题目来源 力扣每日一题&#xff1b;题序&#xff1a;1883 我的题解 方法一 动态规划浮点数精度 参考官方题解。 用 f[i][j]表示经过了 dist[0]到 dist[i−1]的 i 段道路&#xff0…

ORACLE错误提示概述

OceanBase分布式数据库-海量数据 笔笔算数 保存起来方便自己查看错误代码。 ORA-00001: 违反唯一约束条件 (.) ORA-00017: 请求会话以设置跟踪事件 ORA-00018: 超出最大会话数 ORA-00019: 超出最大会话许可数 ORA-00020: 超出最大进程数 () ORA-00021: 会话附属于其它某些进程…

PTA L2-047 锦标赛

题目 解析 把每一场比赛看作满二叉树的一个节点&#xff0c;父节点递归遍历子节点的结果&#xff0c;进行试填。 代码 #include <bits/stdc.h>using i64 long long;struct Node {int win, lose; };void solve() {int k;std::cin >> k;int siz (1 << k);…

【YOLOv8改进[Backbone]】使用MobileNetV3助力YOLOv8网络结构轻量化并助力涨点

目录 一 MobileNetV3 1 面向块搜索的平台感知NAS和NetAdapt 2 反向残差和线性瓶颈 二 使用MobileNetV3助力YOLOv8 1 整体修改 ① 添加MobileNetV3.py文件 ② 修改ultralytics/nn/tasks.py文件 ③ 修改ultralytics/utils/torch_utils.py文件 2 配置文件 3 训练 其他 …

如何查看项目中使用的Qt版本

如何查看项目中使用的Qt版本 1.点击左下角电脑按钮查看Qt版本。 2.点击左侧栏项目按钮查看Qt版本。

apipost、postman等工具上传图片测试flask、fastapi的文件api接口

参考&#xff1a;https://blog.csdn.net/qq_15821487/article/details/119354129 https://www.cnblogs.com/wyxjava/p/16076176.html 选择from-data&#xff0c;下拉选择file上传文件发送即可

MySQL-数据库基础

一、背景与基本使用 首先是登录方式&#xff0c;一般用 mysql -h 127.0.0.1 -P 3306 -u root -p mysql也是一种网络服务。 当然我们在本地登录时可以省去主机ip和端口号。 -h表示我们要登录mysql在哪个ip的主机上&#xff0c; -P表示端口号。 -u表示以谁的身份去登录。…

笔记:Python顺序结构 练习题

文章目录 前言一、什么是顺序结构&#xff1f;二、练习题1.题目2.填空题3.简答题4.编程题 总结 前言 本次笔记旨在帮助读者加深对Python编程语言中顺序结构和选择题的理解。在学习Python编程过程中&#xff0c;掌握程序的基本结构以及条件语句的使用至关重要。通过本次练习题&…

MyBatis使用PageHelper分页插件

1、不使用PageHelper分页插件 模块名&#xff1a;mybatis-012-page CarMapper接口package org.example.mapper;import org.apache.ibatis.annotations.Param; import org.example.pojo.Car;import java.util.List;public interface CarMapper {/*** 分页查询* param startInd…

Python中的字符串操作

Python 是一种简单易学且功能强大的编程语言&#xff0c;它在处理字符串方面提供了丰富的内置方法和函数。字符串是 Python 中最基本的数据类型之一&#xff0c;用于表示文本数据。本文将介绍 Python 中一些常用的字符串操作方法&#xff0c;并通过示例代码来展示它们的用法。 …

【爬虫】多线程爬取图片

多线程爬虫 多线程爬虫概述1.1 多线程的优势1.2 多线程的挑战 设计多线程爬虫1.1 项目设计1.2 项目流程1.3注意事项 总结 多线程爬虫概述 在当今信息爆炸的时代&#xff0c;网络爬虫&#xff08;Web Scraper&#xff09;已成为获取和分析网络数据的重要工具。而多线程爬虫&…

贪吃蛇游戏源码(VS编译环境)

贪吃蛇游戏源码&#xff08;VS编译环境&#xff09; &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;C语言&#x1f353; &#x1f33c;文章目录&#x1f33c; 1. Snake.h 头文件 2. Snake.c 源文件 3. Test.c 头文件 1. Snake.h 头…

什么是promise?

一个对象&#xff0c;用来处理异步操作。使异步操作写的更优雅、更易于阅读。 从字面上理解&#xff0c;promise是承诺、许诺的意思。意思是使用promise后&#xff0c;不管成功还是失败肯定会有返回值。 promise有三种状态&#xff1a;pending&#xff08;进行中&#xff09;&a…

linux常用命令,没有最全,只有更全 【持续更新】

工作中linux是大家常用的&#xff0c;下面这些linux命令涵盖了工作中常用的&#xff0c;相信你百分百会用的到&#xff01; 文件和目录操作&#xff1a; ls&#xff1a;列出当前目录下的文件和子目录。 例如&#xff1a;ls -l 显示详细信息&#xff0c;ls -a 显示所有文件&…

Dubbo元数据中心

元数据中心为 Dubbo 中的两类元数据提供了存取能力&#xff1a;地址发现元数据、服务运维元数据。 一、地址发现元数据 Dubbo3 中引入了应用级服务发现机制用来解决异构微服务体系互通与大规模集群实践的性能问题&#xff0c;应用级服务发现将全面取代 2.x 时代的接口级服务发…

java的常规算法有那些?

在Java编程中&#xff0c;有一系列常规算法被广泛应用&#xff0c;这些算法涵盖了排序、搜索、字符串处理等多个领域。下面列出了一些基本的算法和它们在Java中的应用&#xff1a; 排序算法 冒泡排序&#xff1a;通过重复遍历待排序列&#xff0c;比较相邻元素&#xff0c;将…

C/C++易错知识点(4):static修饰变量和函数

static是C/C中一个非常容易混淆的语法&#xff0c;在不同的地方针对不同的对象有不同的效果。 它在大型项目中有至关重要的作用&#xff0c;需要我们详细研究。 1.变量 所有static修饰的变量的生命周期都是自调用它起到程序结束&#xff0c;期间这些变量都只会初始化一次 ①…