【问题标题】:When linking statically, does the linker include the whole library?静态链接时,链接器是否包含整个库?
【发布时间】:2012-03-10 14:29:24
【问题描述】:

例如,如果我静态链接到 freeglut,编译器是包含来自 freeglut 的所有内容还是仅包含我使用的部分?当然,这意味着链接器(或编译器?)会进行某种依赖分析以找出它可以安全排除的内容。

如果是这样,有没有办法查看 Visual Studio 中包含或排除的内容?

【问题讨论】:

    标签: c++ c visual-studio-2010


    【解决方案1】:

    这部分是实施质量问题,但确实存在问题。

    也就是说,按照标准,链接器必须添加所有被引用的编译单元。但是说在库中,你有一个编译单元,只有一个静态变量,它的初始化注册了一些东西注册表,例如消息处理、工厂等,或者可能是它的构造函数和析构函数输出,分别是“在 main 之前”和“在 main 之后”。如果没有引用该编译单元中的任何内容,则链接器有权跳过它,将其删除。

    因此,为了确保此类静态变量不会被优化掉,使用符合标准的工具链,引用该编译单元中的某些内容是必要且足够的。

    重新查看 Visual Studio 中包含的内容,据我所知,除了要求链接器提供详细输出之外别无他法,例如链接器选项 /verbose:ref

    但是,使用该选项,您会得到真正详细的输出。

    另一种方法是向链接器询问映射文件,例如链接器选项/map:blah

    不过,这个输出也非常冗长。

    【讨论】:

    • 这反映了我的测试结果。我在同一个 C++ 文件中构建了一个包含两个函数的简单库。当我链接到这个库时,这两个函数都包括在内,即使我只使用其中一个。如果我将这些函数拆分为两个 C++ 文件(生成两个 obj 文件),则只有我在应用程序中使用的函数会被包含在内。
    • @PavanManjunath:在神圣标准中,它被称为翻译单元。实际上,这是您在预处理某些实现文件(例如 cpp 文件)后所拥有的。整个事情在标准开始处的“翻译阶段”中进行了描述。
    • 这不仅是链接器的实现质量问题,而且是您正在使用的特定库的问题。如今,大多数库都是由不了解链接器或翻译单元用途的人编写的,他们基本上使用库的任何一项功能来实现几乎整个库。尝试静态链接使用printf 甚至只是puts 与glibc 的“hello, world”程序(它将> 500k),或者更糟糕的是,使用来自libstdc++ 的iostream 的C++“hello world”程序(它'将> 900k)。我怀疑 freeglut 在这方面很糟糕......
    【解决方案2】:

    是的,链接器将只包含您的代码引用的翻译单元。

    如果您为您的可执行文件生成一个映射文件,那么您可以准确地看到它包含的内容。

    【讨论】:

      【解决方案3】:

      链接器只包含需要的符号。

      about inspecting *.lib files 的问题可能回答了第二部分(dumpbin 也适用于 *.exe 文件)。

      【讨论】:

      • dumpbin/code> 似乎在带有调试信息的 exe 中也找不到普通符号。
      【解决方案4】:

      我认为您可以编写一个示例库来获得答案。 在 C++ 库中, 1 写一个类来打印所有的子类名。 2 以及从它派生的几个类。

      在真正的主程序中,只使用其中一个子类。

      然后打印所有的名字。

      我想你会找到答案的。

      【讨论】:

      • 请提供答案,而不是谜语。这是一个问答平台。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-15
      • 1970-01-01
      • 2018-12-11
      • 1970-01-01
      • 1970-01-01
      • 2021-06-13
      相关资源
      最近更新 更多