将静态本机库链接到托管C ++项目会在 [英] Linking static native library to managed C++ project pulls unused (and unexpected) dependencies in

查看:149
本文介绍了将静态本机库链接到托管C ++项目会在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简介:

托管( / clr )C ++项目( .dll )静态链接本机C ++库(使用 / MD 编译)。静态库很大,并引用了许多其他库,但是托管C ++代码使用的功能微不足道,不应引入任何其他依赖项。

Managed (/clr) C++ project (.dll) statically links native C++ library (which is compiled with /MD). Static library is big and references a lot of other libraries, but functionality used by managed C++ code is trivial and shouldn't pull in any additional dependencies.

问题:


  1. 由于 LNK2001 LNK2019 提到代码绝对不依赖的符号

  2. 即使我添加了必需的依赖项,也要切换工具集(例如,从 VS2017 迁移到 VS2019 )导致错误再次出现(这次提及其他依赖项)

  1. linking fails with LNK2001 and LNK2019 mentioning symbols that code definitely does not depend on
  2. even if I add required dependencies, switching toolset (e.g. migrating from VS2017 to VS2019) causes errors to come back (this time mentioning other dependencies)

会发生什么:

显然, / clr 开关使编译器对内联函数的处理方式有所不同-它们不再嵌入 .obj 文件(作为弱符号),而是在导入表中引用它们。这意味着链接器必须查找以下内容:

Apparently, /clr switch causes compiler to treat inlined functions differently -- they are no longer get embedded into .obj files (as "weak symbols"), instead they get referenced in the table of imports. This means linker has to find things like:

"public: virtual char const * __cdecl std::exception::what(void)const " (?what@exception@std@@UEBAPEBDXZ)

...这样做和(因为CRT库 DEFAULTLIB ,因此最后使用),通常会在其他库(即上述静态本地lib)中找到它。因此,它将在静态lib中找到第一个 .obj 文件,该文件包含 std :: exception :: what()并提取它-意味着我们现在依赖于 .obj 依赖的所有内容。这说明了问题1(虚假的链接器错误)。

... which it does and (since CRT libraries are DEFAULTLIB and therefore are used last) typically it finds it in other library (namely, in aforementioned static native lib). So, it finds first .obj file in static lib that contains std::exception::what() and pulls it in -- meaning we now depend on everything said .obj depends. This explains problem #1 (bogus linker errors).

现在,如果您使用其他工具集( obj 文件)编译静态库,可以按不同的顺序存储,从而导致问题2。

Now, if you compile your static lib with another toolset -- obj files can be stored in different order, causing problem #2.

要重现此问题,可以使用以下代码(确保托管项目链接为静态lib):

To reproduce the issue you can use this code (make sure managed project links static lib):

//--------------------
// statlib.cpp
//
#include <exception>

void this_is_a_trap() { throw std::exception(); }

extern int bar();

int foo() { return bar(); }


//--------------------
// clrdll.cpp (managed code)
//
#include <exception>

__declspec(dllexport) void oops()
{
    throw std::exception();
}

如果使用 / VERBOSE 标志链接您会看到类似的东西:

If you link with /VERBOSE flag you'll see smth like:

1>    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64\oleaut32.lib:
1>    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64\uuid.lib:
1>    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64\odbc32.lib:
1>    Searching C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64\odbccp32.lib:
1>    Searching C:\tst\x64\Release\statlib.lib:
1>      Found "public: virtual char const * __cdecl std::exception::what(void)const " (?what@exception@std@@UEBAPEBDXZ)
1>        Referenced in clrdll.obj
1>        Loaded statlib.lib(statlib.obj)   <-- Now we depend on `bar()`

问题

处理此问题的最佳方法是什么?

What is the best way to deal with this?

注意:


  • msvcrt.lib 添加到链接器输入(在其他静态库之前)会有所帮助,但并非总是如此-某些符号(如 std :: bad_weak_ptr :: what()不存在于 msvcrt.lib 中)

  • adding msvcrt.lib to linker inputs (before other static libs) helps, but not always -- certain symbols (such as std::bad_weak_ptr::what() aren't present in msvcrt.lib)

此问题是此SO帖子

推荐答案

使用混合代码( / clr 和本机代码) std :: exception :: what()(和其他类似符号)执行内联,但是这些定义受托管(非本地)。通常这不是问题,但是本机代码通过 std :: exception 的vtable引用 native 定义。通常,将这种引用(一旦解析失败)重定向到托管定义(如上所述,生成的托管定义),但是在这种情况下-本地定义是在另一个对象(来自本地静态库的随机对象)中找到重定向插入,导致该对象被引用。

In mixed (/clr and native) code std::exception::what() (and other similar symbols) do get inlined, but these definitions are managed (not native). Which normally is not an issue, but native code refers to native definition via std::exception's vtable. Normally, such reference (once it fails to resolve) gets redirected to managed definition (which is generated, as stated above), but in this case -- native definition is found in another object (random object from native static library) before "redirection" kicks in, causing that object to be referenced.

查看详细信息此处。 MS正在寻找解决此问题的最佳方法。

See details here. MS is figuring out a best way to deal with this.

这篇关于将静态本机库链接到托管C ++项目会在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆