linux编译时-ldl,编译和链接C文件时关于-ldl标志

本文探讨了C++代码中使用dlsym函数动态链接库时遇到的问题。当-dl标志的位置改变导致链接错误时,解释了原因在于库和对象文件的链接顺序。同时,确认在没有动态加载库的情况下,保存原始rand()函数指针为静态变量是安全的。文章还提到了静态变量在多线程环境中的线程安全性考虑。
摘要由CSDN通过智能技术生成

参考以下代码

test_linker.cpp

int main() {

srand(time(0));

for (int i = 0; i < 10; ++i) {

cout << rand() % 10 << endl;

}

return 0;

}

urandom.cpp

#include

using std::cout;

using std::endl;

#include

int rand() throw() {

// get the original rand() function

static auto original_rand = (decltype(&rand)) dlsym(RTLD_NEXT,"rand");

cout << "Call made to rand()" << endl;

return original_rand();

}

当我尝试使用以下命令编译代码时

g++ -std=c++11 -Wall -Werror -Wextra -Wvla -pedantic -O3 urandom.cpp -c

g++ -std=c++11 -Wall -O3 test_linker.cpp urandom.o -ldl

一切正常,但是当我将-ldl标志移动到文件之前时,链接器会抛出一个错误说

urandom.cpp:(.text+0xaf): undefined reference to `dlsym'

问题1有人可以解释为什么会这样吗?我通常不关心编译命令中的标志顺序.

问题2将原始rand()函数的函数指针保持为静态变量也是错误的吗?我不知道动态链接是如何工作的,我担心函数地址可能会在运行时在内存中移动.手册页说,带有RTLD_NEXT句柄的dlsym()函数是一个昂贵的计算,所以我只想懒洋洋地评估一次.

注意:我正在Linux发行版上编译它,并且涉及Linux动态链接器,因此我将继续使用Linux进行标记.

解决方法:

-ldl是链接器的库名称.它告诉链接器查找并链接名为libdl.so(或有时是libdl.a)的文件.它与在命令行的相同位置放置相关库的完整路径具有相同的效果.

命令行上的库和对象顺序很重要.通常,如果库A调用库B,则应将B放在命令行中的A之后.所有库通常应该遍历所有目标文件.这在几个SO问题和答案中被广泛涵盖,如this one.

至于第二个问题,不,函数的地址在运行时不会改变,除非您打开共享库,然后卸载它,然后再次执行它.在您的情况下,由于您没有dlopen库,因此将函数地址保存在静态变量中是安全的.当然,如果你运行多个线程,你需要以某种方式确保线程安全(互斥它,或使用线程本地存储).

标签:c-2,linux,c11,dynamic-linking

来源: https://codeday.me/bug/20190519/1135714.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值