【问题标题】:Visual Studio Force Library Import C++Visual Studio Force 库导入 C++
【发布时间】:2019-01-27 03:44:53
【问题描述】:

我有两个 Visual Studio C++ 项目,它们生成以下输出:

L.lib
E.exe

我想在 E.exeL.lib 之间添加一个依赖项,而不实际调用从 L.lib 导出的任何方法. L.lib 导出单个函数:

__declspec(dllexport) unsigned foo();

然后在E.exe中,我有如下编译单元:

// L.cpp
#pragma comment(lib, "L.lib")
extern unsigned foo();

问题在于,由于 E.exe 未使用 foo,因此优化了对 L.lib 的依赖。在不实际执行任何代码的情况下强制依赖 L.lib 的最佳方法是什么?我能想到的最好的方法如下(从上面附加到 L.cpp):

__declspec(dllexport) decltype(&foo) bar{ foo };

但是,以上导致在链接过程中生成额外的文件(E.lib 等),并将公共方法添加到生成的E.exe 可执行文件。谁能想到一个更好的方法来强制进入 EXPORTS 表?

我知道我可以禁用链接器优化以删除未使用的代码,但这会影响整个 E.exe,我不想这样做。

更多信息

我看到的问题是 E.exe 对第三方 L.lib(以及相关的 L.dll) 是不可重定位的(例如,与/FIXED 选项链接)。当 L.dll 被加载时,它需要加载的固定内存地址已被 E.exe 加载的其他 DLL 占用。我需要一种方法来确保尽早加载 L.dll,以防止另一个 DLL 获取 L.dll 正常运行所需的内存地址.

【问题讨论】:

    标签: c++ visual-studio dll visual-studio-2015 linker


    【解决方案1】:

    只需将foo的地址以无法优化的方式取出:auto volatile pFoo = &foo;。它实际上并没有被调用,但编译器无法证明它没有被调用,所以它必须安全。

    [编辑] 使用 LTCG,Visual Studio 显然比我想象的更激进。添加pFoo=pFoo; 修复它。链接器映射:0003:0000037c ?pFoo@@3R6AXXZA 0040337c

    【讨论】:

    • 这个解决方案适用于我的绝大多数项目。但是,它在包含大约 4 行代码的项目中仍然失败,并且使用 wmain 而不是 main。关于如何在这种情况下欺骗编译器的任何其他想法?
    • @JeffG; wmain 是一个红鲱鱼。这是链接器真正不关心的细节级别。另外,我不知道“失败”是什么意思。 pFoo 不是指向 foo 的指针吗?如果是,则必须已加载 foo
    • 失败 意味着 VS2015 链接器仍在确定 pFoo 未使用,因此未添加对 L.lib 来自生成的 E.exe。我验证了无论我使用main还是wmain,结果都是一样的(链接器正在优化pFoo)。
    【解决方案2】:

    虽然 MSalters 回答在 90% 的情况下有效,但它始终无法从 E.exe 添加对 L.lib 的引用。此外,他的编辑建议需要修改可执行文件使用的函数体。我正在寻找一种解决方案,只需要包含一个发送到链接器的附加源文件(编译单元)。

    经过进一步调查,我确定以下代码正是这样做的:

    // L.cpp
    #pragma comment(lib, "L.lib")
    extern "C" unsigned foo();
    #pragma comment(linker, "/include:_foo")
    

    这会迫使您知道 foo 的错误名称,但由于 extern "C" 声明,我的情况很容易确定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-23
      • 2019-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-04
      • 1970-01-01
      相关资源
      最近更新 更多