【问题标题】:How to eliminate Warning LNK4221?如何消除警告 LNK4221?
【发布时间】:2014-01-18 05:04:20
【问题描述】:

我正在使用 c++/windows 表单 (visual studio 2010) 开发一个项目,我们有 4 个项目:

  • 1 个项目包含 GUI 窗口窗体 {托管代码},这是 exe 项目
  • 其他 3 个项目 {非托管代码} 都是静态库。
  • 在 4 个项目中,我们不使用预编译头文件 stdafx.h ,公共语言运行时支持是纯 MSIL 公共语言运行时支持 (/clr:pure)。
  • 每个项目都包含其他 3 个项目作为附加包含目录,并将链接库依赖项设置为是。

我们有:

警告 LNK4221:此目标文件未定义任何以前未定义的公共符号,因此任何使用此库的链接操作都不会使用它

此警告针对同一对象文件 (.NETFramework,Version=v4.0.AssemblyAttributes.obj) 中的 3 个静态库项目。

我们想消除它,但经过一番搜索,大多数主题都说预编译的标头是我们不使用它的一个原因。

关于为什么存在此警告以及如何消除它的任何新想法?

【问题讨论】:

  • 为什么不使用预编译头文件?与此警告链接的目标文件是什么 - 请发布链接器错误。是否编译和链接了 stdafx.cpp 文件?
  • @ManuelH 的链接显示了第一个谷歌点击,这很好地解释了它!
  • @Alex:我没有使用预编译的头文件,因为它产生了几个错误,关于哪些目标文件,这个警告出现在同一个目标文件中的 3 个静态库项目(\.NETFramework,Version =v4.0.AssemblyAttributes.obj),并且项目中没有stdafx文件。

标签: c++ linker


【解决方案1】:

免责声明:这个解决方案确实很糟糕,这个代码不应该被添加到生产构建中!只有“隐藏”警告才有用。

更好的解决方案是从编译中删除有问题的文件,因为它无论如何都没用。

原帖:

我遇到了来自多个依赖项的警告的问题,我发现它是由某些翻译单元为空引起的,即空源文件。

这些文件实际上有内容,但在 Visual Studio 中已停用,所以我只是在开头添加:

__declspec( dllexport ) void getRidOfLNK4221(){}

现在我的项目编译没有任何警告:)

希望它有所帮助,即使这是一个迟到的答案!

【讨论】:

  • 太糟糕了。
  • 为什么这么可怕?
  • 代码基本上创建了一个什么都不做的函数,然后告诉编译器不要删除它,实际上将它作为一个符号公开。首先它是“可怕的”,因为你试图说服编译器不要告诉你它看到你做的一些愚蠢的事情——然后通过使用随机垃圾函数污染你的符号表和库二进制文件来使问题复杂化,根据定义,这些垃圾函数是毫无意义的。一个更好的解决方案是修复警告——在这个答案的情况下,根本不编译无用的文件。按平台将实现拆分为文件,无论如何它都会编译得更快。
【解决方案2】:

我有一个 c++ 静态库,其中有一个空模块,在非优化模式下链接它给了我 LNK4221 警告。 (在 Visual Studio 中) 我去了图书馆员->所有选项,并在附加选项中添加了“/ignore:4221”。 所以,警告消失了。

【讨论】:

    【解决方案3】:

    您收到此警告是因为您仅在 cpp 文件中使用模板类。 为了摆脱它,插入一个没有模板的简单函数。

    【讨论】:

    • 我听从了你的建议。这个警告没有了。但是对于包含标题的每个其他文件,都会出现一个新的 LNK4006(:
    • 这是我的 VS2013 静态库项目方案。我在 .h 文件和相应的(空).cpp 文件中有一个完全模板化的类。我只是从项目中排除了 .cpp 文件。警告消失了,当我使用静态库构建可执行文件时,我(令我惊讶,但不应该如此)没有链接错误。
    【解决方案4】:

    看到这个: https://docs.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-warning-lnk4221

    总而言之,文件没有导出任何内容,因此链接器不会链接,因为它认为这是浪费精力

    【讨论】:

      【解决方案5】:

      这只是我的特殊问题,但如果您的 .cpp 没有定义任何新函数或构造函数的主体为空,您将收到此警告。我为我的构造函数使用了一个初始化列表,所以主体是空的。

      【讨论】:

        【解决方案6】:

        https://devblogs.microsoft.com/cppblog/linker-warning-lnk4221-and-some-tips-to-avoid-it/

        在“Visual Studio 2008 命令提示符”中,输入以下命令(注意:我们在这里使用命令行来指定 .obj 文件的顺序;Visual Studio 2008 将按字母顺序提供带有 .obj 文件的链接器)

        cl /c a.cpp b.cpp

        链接 /lib /out:test.lib a.obj b.obj

        LNK4221 会为 a.obj 抛出如下。

        a.obj : warning LNK4221: no public symbols found; archive member will be inaccessible
        

        对于上述情况,atlbase.h(随 Visual Studio 提供)包含一些符号定义,它们将包含在 a.objb.obj 中。此外,b.obj 中定义了一个函数 func1。链接器会以后进先出的方式处理 OBJ 文件,所以在处理a.obj 时,由于b.obj 提供了a.obj 拥有的所有公共符号,所以在其中找不到任何新的公共符号,将抛出 LNK4221。如果命令行2替换为以下

        链接 /lib /out:test.lib b.obj a.obj

        现在警告消失了!

        【讨论】:

          猜你喜欢
          • 2010-12-21
          • 2021-01-16
          • 2022-01-21
          • 2021-11-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-14
          相关资源
          最近更新 更多