【问题标题】:About the -ldl flag while compiling and linking C++ files关于编译和链接 C++ 文件时的 -ldl 标志
【发布时间】:2016-05-21 08:14:20
【问题描述】:

参考以下代码

test_linker.cpp

int main() {

    srand(time(0));
    for (int i = 0; i < 10; ++i) {
        cout << rand() % 10 << endl;
    }

    return 0;
}

urandom.cpp

#include <iostream>
using std::cout;
using std::endl;
#include <dlfcn.h>

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 不仅仅是一个标志,它是一个库名称,命令行中库和目标文件的顺序很重要。
  • Q2:不,在静态中 kiip 并没有错(只要你是单线程的)。函数的地址在运行时不会改变。
  • 如果你有时间,你能解释一下你的答案吗?

标签: c++ linux c++11 dynamic-linking


【解决方案1】:

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

命令行上的库和对象顺序确实很重要。通常,如果库 A 调用库 B,则 B 应放在命令行上的 A 之后。所有库通常都应该在所有目标文件之后。这在诸如this one 之类的几个 SO 问题和答案中得到了广泛的介绍。

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

【讨论】:

  • 感谢您的回答!你能解释一下为什么在这种情况下使用 dlopen 会不好吗?
  • 当你打开一个库时,你会加载它的所有函数和数据;当您卸载它时,所有功能和数据将不复存在且不再可访问;当您再次 dlopen 时,您正在将其加载到可能不同的内存区域。
【解决方案2】:

从你的第二个问题开始,动态链接在运行时工作,无论是在 C/C++ 中,我们都调用这个 -> 操作的稍后绑定。当然,当您调用以后声明为接口或类实例的绑定时,应该指向该对象的指定对象和内存位置。

我认为第一个问题更具体到编译器。我猜你不是在 Visual Studio 中编译(不是在 Windows 操作系统中),如果我是对的,你应该要求编译器的供应商配置调试属性。 :)

【讨论】:

  • 哦,顺便说一下你的 Q2,如果指定的函数在运行时被声明为 volatile(但这取决于编译器属性和你使用的编译器),那么该函数可能会改变内存位置的行为: )
猜你喜欢
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多