首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Linux上加载共享库延迟

问如何在Linux上加载共享库延迟
EN

Stack Overflow用户
提问于 2014-05-01 07:35:39
回答 3查看 8.2K关注 0票数 13

我一直在寻找一种方法来创建一个共享库(让我们命名为库libbar.so),延迟加载在Linux上的,希望在的帮助下实现--只使用链接器,而不是修改用C++编写的源代码上的任何内容;我的意思是,我不想在父库的源代码中调用dlopen()或dlsym() (让我们命名为libfoo.so)来调用libbar.so的一个函数,因为它们会使源代码变得混乱和维护过程困难。(简而言之,我希望使用类似于Visual的/DELAYLOAD选项的方式,即使是在Linux上)

无论如何,到目前为止,我在互联网上发现了一些与我的问题有关的不确定的信息片段,所以很高兴能从你们那里得到以下问题的答案,以使信息变得清晰。

  1. GNU 是否支持在Linux上的延迟加载机制?
  2. 如果没有,那么Clang怎么样?
  3. dlopen() 家庭是在Linux上加载共享库延迟的唯一方法吗?

我测试了将-zlazy标志传递给GCC (g++)的路径,它似乎接受了该标志,但该行为并没有使libbar.so延迟加载(没有libbar.so,我希望在libbar.so的第一次调用时出现异常,但在进入libfoo.so之前实际引发了异常)。另一方面,Clang (clang++)留下了一个警告,即它忽略了选项标志。

诚挚的问候,

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-05-01 08:44:41

延迟加载不是运行时特性。MSVC++在没有Windows帮助的情况下实现了它。就像dlopen是Linux上的唯一方法一样,GetProcAddress也是Windows上唯一的运行时方法。

那么,延迟装载是什么呢?这很简单:任何对DLL的调用都必须经过指针(因为您不知道它将在哪里加载)。这一直由编译器和链接器为您处理。但是,通过延迟加载,MSVC++首先将这个指针设置为一个存根,该存根为您调用LoadLibrary和GetProcAddress。

没有ld的帮助,Clang也可以这样做。在运行时,它只是一个普通的dlopen调用,而Linux无法确定Clang是否插入了它。

票数 12
EN

Stack Overflow用户

发布于 2014-05-01 09:18:07

可以使用代理设计模式以可移植的方式实现此功能。

在代码中,它可能如下所示:

代码语言:javascript
复制
#include <memory>

// SharedLibraryProxy.h
struct SharedLibraryProxy
{
    virtual ~SharedLibraryProxy() = 0;

    // Shared library interface begin.
    virtual void foo() = 0;
    virtual void bar() = 0;
    // Shared library interface end.

    static std::unique_ptr<SharedLibraryProxy> create();
};

// SharedLibraryProxy.cc
struct SharedLibraryProxyImp : SharedLibraryProxy
{
    void* shared_lib_ = nullptr;
    void (*foo_)() = nullptr;
    void (*bar_)() = nullptr;

    SharedLibraryProxyImp& load() {
        // Platform-specific bit to load the shared library at run-time.
        if(!shared_lib_) { 
            // shared_lib_ = dlopen(...);
            // foo_ = dlsym(...)
            // bar_ = dlsym(...)
        }
        return *this;
    }

    void foo() override {
        return this->load().foo_();
    }

    void bar() override {
        return this->load().bar_();
    }
};

SharedLibraryProxy::~SharedLibraryProxy() {}

std::unique_ptr<SharedLibraryProxy> SharedLibraryProxy::create() {
    return std::unique_ptr<SharedLibraryProxy>{new SharedLibraryProxyImp};
}

// main.cc
int main() {
    auto shared_lib = SharedLibraryProxy::create();
    shared_lib->foo();
    shared_lib->bar();
}
票数 6
EN

Stack Overflow用户

发布于 2018-02-16 09:58:19

要添加到MSalters答案中,可以很容易地模仿Windows在Linux上延迟加载的方法,方法是创建一个小的静态存根库,在第一次调用它的任何函数时尝试dlopen所需的库(发出诊断消息并在dlopen失败时终止),然后将所有调用转发给它。

这样的存根库可以手工编写,可以由特定于项目/库的脚本生成,也可以由通用工具Implib.so生成。

代码语言:javascript
复制
$ implib-gen.py libxyz.so
$ gcc myapp.c libxyz.tramp.S libxyz.init.c ...
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23403848

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档