【问题标题】:C++ linker issuesC++ 链接器问题
【发布时间】:2009-10-26 12:01:21
【问题描述】:

我有这个:

a.cpp

int localfunction () { return 1; }
int local_symbol = localfunction();

b.cpp

void thirdfunction () {};

main.cpp

void main () { thirdfunction (); }

当我在主可执行文件中编译它时,一切正常(即使进行了优化),并且本地函数在启动时执行,即使我不直接调用它也是如此。

现在,在 Visual C++ 和 GCC 中,我将 a.cpp 和 b.cpp 放在静态库 (.lib) 中。 localfunction 不再被执行/定义。

据我了解,该符号被检测为“未使用”并被删除。但这听起来很奇怪,因为:

  • 为什么我不使用 .lib 文件时它没有被删除?
  • 既然链接了lib,为什么链接器会炸掉初始化代码?

我想要做的是在我使用的每个 .lib 文件中都有一组启动函数,自动注册一些数据。主可执行文件不应该知道链接了哪些文件,也不应该明确引用“localfunction”(/INCLUDE 确实有效,但不是最佳的)

顺便说一句:使用各种 VC++ 选项(OPT:NOREF 等)并不能解决问题。

谢谢! QbProg

【问题讨论】:

    标签: c++ visual-c++ linker reference


    【解决方案1】:

    静态库基本上是从该库的组成源文件编译的目标文件的库或存档。

    当链接器在构建应用程序时使用静态库来解决依赖关系时,它会遵循一个在库中查找目标文件的过程,以帮助它解决程序中的任何未定义符号。它不会自动包含库中的所有目标文件。

    在您的实例中,从main.cpp 生成的目标文件引用third_function()。这种依赖关系可以通过链接从b.cpp 生成的目标文件来解决。该目标文件不再引入未定义的符号,因此链接器可以(并且确实)在此停止。

    哦,为了最大的便携性,main 应该返回int

    【讨论】:

    • 但是当我不使用 lib 文件时,函数会被保留并执行!为什么会有这种不同的行为?
    • 这是因为当源不在库中时,它是您应用程序的一部分。链接器使用库来帮助完成程序,但它不会包含来自库的“不必要的”目标文件。当您指定一个非库目标文件作为应用程序的一部分包含时,链接器将始终包含该目标文件,即使您的应用程序的其余部分不依赖它。
    【解决方案2】:

    当使用 gcc 并且需要在 main() 运行之前“自动”运行的启动函数时,我会使用 __attribute__((constructor))

    也许有一种类似的方式(pragma?)在 VC++ 中定义一个函数,然后你可以做一些预处理宏魔术来有一个通用的方式来声明这些启动函数。

    【讨论】:

    • 这个属性是有用的,但它在相同的场景(lib 文件)中不起作用。
    【解决方案3】:

    您的链接器将采取措施减小可执行文件的大小。它将确定您的 exe 不使用 'said' 函数并且不将其包含在其最终生成的代码中。虽然这也取决于您在项目中使用的优化。

    如果您希望动态执行此操作,更好的选择是使用 LoadLibrary 并创建一个所有程序都可以加载的 DLL,并动态加载函数并注册您需要的内容。

    【讨论】:

      【解决方案4】:

      你必须记住过去的尺寸是非常重要的。

      您拥有一个包含 10,000 个不同函数的庞大数学库。 现在您的应用程序使用 sin() 并且您链接到 libm.a(或 -lm)。

      您绝对不想在您的应用程序中添加 9,999 个您不使用的函数。因此,当使用静态库时,它只会从库中准确提取所使用的内容(仅此而已)。

      另一方面,共享库的设计目的是让整个东西都被拉入内存。此外(尽管它没有在任何标准中定义)大多数动态加载器也会在加载时运行任何静态初始化代码。 (请注意,如果您链​​接它们,它们通常会在应用程序启动时加载)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-10
        • 2016-10-24
        • 1970-01-01
        • 1970-01-01
        • 2010-11-17
        • 2019-01-20
        相关资源
        最近更新 更多