c++ - Linux - 动态和静态加载时调用相同的函数

标签 c++ linux cmake shared-libraries dlopen

我有一个编译为 .so 文件的 c++ 项目(使用 g++5 编译)。 在另一个项目中(在同一解决方案下)我有一个链接到该项目的测试(CMake 的命令 target_link_libraries(...))。

我编译项目,并将输出的 .so 文件复制到“/tmp/proj.so”。

除了将测试链接到项目外,我还使用dlopen动态加载“/tmp/proj.so”,它有一个全局函数create_foo,它创建一个新的 foo 对象。

我想要实现的目标是进行一项测试,将同一项目的两个版本进行比较,这样我就知道我不会通过更改项目中的内容来破坏任何东西。

使用dlopen 打开后,我调用dlsym 来查找create_foo,然后调用它。 create_foo 是类似的东西:

extern "C" bool create_foo(foo** instance){
    *instance = new foo();
    return true;
}

所以在我的测试中我有类似的东西(我删除了不相关的代码,比如空检查):

#include <dlfcn.h>
#include "foo.h"

int main()
{
    foo f1;
    void* handle = dlopen("/tmp/proj.so", RTLD_NOW);
    bool(*create_foo_func)(foo**);
    create_foo_func = (bool(*)(foo**))dlsym(handle, "create_foo");

    foo* f2;
    (*create_foo_func)(&f2);

    assert(f1.bar() == 10);
    assert(f2->bar() == 10);
}

两个断言都可以。 所以我接下来要做的是将 foo::bar 更改为 return 5 而不是 10,编译项目 但我没有更改/tmp/proj.so 文件! 当我运行程序时,我得到:

f1.bar() == 5
f2->bar() == 5 //I would expect this to be 10 since I did not change it

所以我在两次调用中都得到了 5,而不是我希望的 f1.bar()==5f2->bar () == 10

我确定 dll 正在加载并且动态中的 create_foo 被调用(我可以在调试器的模块列表中看到它,如果我尝试 dlsym("NOT_create_foo") 它会失败,另一种方法也会失败,即将 create_foo 函数名称更改为某个名称但不更改/tmp/proj.so)。

当我在代码中添加 printf("static linkage"),编译它并保持/tmp/proj.so"文件不变(意味着它没有这个 printf)时,我看到它被打印了两次。

那么我做错了什么?

我正在从事的实际项目很大并且正在使用 CMake。我可能遗漏了一些我认为不相关的重要细节,如果您认为我应该查看某个地方,请发表评论,我将根据答案进行编辑。

最佳答案

dlopen 手册页没有这么说,但是here , 它说

Only a single copy of an object file is brought into the address space, even if dlopen() is invoked multiple times in reference to the file, and even if different pathnames are used to reference the file.

和 linux dlopen 联机帮助页:

   If the same library is loaded again with dlopen(), the same file handle is returned. 
   The dl library maintains reference counts for library handles, so a dynamic library 
   is not deallocated until dlclose() has been called on it as many times as dlopen() 
   has succeeded on it.

所以看起来 dlopen 将 /tmp/proj.so 视为与已经为测试可执行文件本身加载的库相同的库。您应该能够通过比较返回的句柄来测试它。

关于c++ - Linux - 动态和静态加载时调用相同的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40491415/

相关文章:

c++ - 如何构建独立的clang可执行文件?

c++ - 如何修改 const int 值 C++

python - 在 apache(linux 和 windows)上运行 python 脚本

python - linux中如何控制后台进程

regex - 根据创建日期移动文件

c++ - 如何让 CMake 基于 GCC 版本通过 std=c++14/c++1y 或 c++17/c++1z?

c - 是否可以使用 CMAKE 在 make install 上重新编译一些源文件

c++ - 模板化成员函数和参数转发

c++ - 试图理解数组 C++ 的初始化

C++ 正确的新用法?