【问题标题】:Visual Studio 2010's strange "warning LNK4042"Visual Studio 2010 的奇怪“警告 LNK4042”
【发布时间】:2011-04-11 08:16:35
【问题描述】:

我刚刚被来自 Visual Studio 2010 (C++) 的一些不平凡的警告打了(几乎没有)。

编译给出以下输出:

1 Debug\is.obj:警告 LNK4042:对象指定了多次;其他被忽略
1 Debug\make.obj:警告 LNK4042:对象指定了多次;其他被忽略
1 Debug\view.obj:警告LNK4042:对象指定了不止一次;其他被忽略
1 identity.obj:错误LNK2019:函数void __cdecl test::identity::identity(void)(?identity@0test@@YAXXZ)中引用的未解析外部符号void __cdecl test::identity::view(void)(?view@identity@test@@YAXXZ)
1 identity.obj:错误LNK2019:函数void __cdecl test::identity::identity(void)(?identity@0test@@YAXXZ)中引用的未解析外部符号void __cdecl test::identity::make(void)(?make@identity@test@@YAXXZ)
1 range.obj : 错误 LNK2019: 函数 void __cdecl test::range::range(void) (?range@0test@@YAXXZ) 中引用的未解析外部符号 void __cdecl test::range::is(void) (?is@range@test@@YAXXZ)

链接器错误总是很难调试...但是有未解决的引用,所以我检查了...但源代码格式正确...最后它击中了我:

我的文件夹层次结构如下所示:

src/
  identity/
    is.cpp
    make.cpp
    view.cpp
  range/
    is.cpp
    make.cpp
    view.cpp

解决方案中的层次结构也是如此(我总是将其设置为模仿“真实”文件夹结构)。

以及诊断输出:

Debug\is.obj
Debug\make.obj
Debug\view.obj

伴随着一条警告说 .obj 已被传递给链接器两次,并且将被忽略。

不再搜索:Visual 已经整齐地展平了我的文件夹层次结构,因此无法整齐地编译源代码。

目前,我只是想重命名文件,这应该可以解决问题...

...但是有没有办法让 Visual Studio 不扁平化文件层次结构?

【问题讨论】:

  • 刚刚得到同样的东西,真的很烦人,我们必须手动“修复”它。很高兴你在我面前问。 :)
  • 我很久以前就放弃了 SO 搜索。 :) 谷歌。
  • 我刚刚在 VS 2013 中解决了一个类似的问题。对我来说,问题是头文件正在被编译,就好像它是一个独立的 C++ 文件一样。所以我最终得到了两个同名的目标文件:一个用于 foo.cpp,一个用于 foo.h。解决方案是转到 foo.h 的正确页面并将 Configuration Properties -> General -> Item Type 更改为“C/C++ header”并进行干净的构建。
  • @AdrianMcCarthy 我遇到了同样的问题,你的建议解决了。
  • @AdrianMcCarthy 的评论是解决方案。一定是由于Add->“New Item”向导自动设置了文件的item类型。

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


【解决方案1】:

我刚刚克服了类似的错误消息,并且通过以下过程获得了更多。症状:对特定标头中定义的每个函数的每次调用都会出现一个链接器错误,并且在标头中定义的每个函数的输出末尾都会出现一个错误。

然后我记得当我最初创建这个头文件时,我不小心选择了“add->new item->c++ file”,虽然我将它命名为“whatever.h”,但似乎 Visual Studio 认为它们都是相同的由于我用来添加文件的操作不正确,导致文件种类繁多。检查构建输出日志后,这一点很明显。

解决方案(使用 VS Community 2019)

  1. 首先备份项目(为了安全起见)。
  2. 右键单击有问题的头文件并选择“从项目中排除”(这不会删除它们;VS 项目只会忽略它们)。
  3. 对匹配的 .c 或 .cpp 文件执行相同操作。
  4. 执行构建->清理项目
  5. Do Build->Rebuild on project -- 当然会有错误---
  6. 右击Header Files->Add->Existing Item,然后选择.h文件
  7. 右键Source Files->Add->Existing Item,选择.c或.cpp文件
  8. Do Build->Rebuild on project。

这完全为我清理了它,让我摆脱了许多恼人的链接器错误,包括这个问题标题中的 LNK4042。

【讨论】:

    【解决方案2】:

    我想指出ItemType.h file 会从C/C++ header 变为C/C++ compiler 的一个可能原因:

    1. 在VS的Solution Explorer窗口(这里是2019),右键项目名称,选择Add -> New Item
    2. 选择C++ File (.cpp)模板,但在名称输入区输入something.h,然后点击OK添加;
    3. 如果something.h 文件包含在多个.cpp 文件中,您将遇到LNK4042 警告。

    【讨论】:

      【解决方案3】:

      右击头文件->属性->ItemType(选择C/C++ Header)。对 Cpp 文件执行相同操作,但选择 C/C++ 编译器(对我有用)

      【讨论】:

      • 这是我最不想寻找的东西。非常感谢。
      【解决方案4】:

      除了删除和创建新文件之外,您还可以更改编译/包含设置。

      转到您的 project.vcxproj 文件,用编辑器打开它,找到类似行 <ItemGroup> 的 html。

      它应该看起来像:

      <ItemGroup>
      <ClCompile Include="implementation.cpp" />
      </ItemGroup>
      

      <ItemGroup>
      <ClInclude Include="declaration.hpp" />
      </ItemGroup>`
      

      假设您的实现文件是 .cpp,而您的声明是 .hpp。如果您有多个声明文件,请确保您的所有实现文件都列在第一部分之间,第二部分同样列出多个声明文件。

      【讨论】:

        【解决方案5】:

        只是想交叉发布我认为是答案的内容,如果您打开整个项目的属性,并将C/C++ -&gt; Output Files -&gt; "Object File Name" 下的值更改为以下内容:

        $(IntDir)/%(RelativeDir)/

        在 VS 2010 下,我相信这将消除所有目标文件的歧义(因为我相信 windows 在任何疯狂的情况下都不会让你在同一个目录中有两个同名的文件)。详情请查看here

        【讨论】:

        • 啊!现在这是我一回到家就需要尝试的东西:D
        • 只是补充一点:似乎 %(RelativeDir) 在你的路径中没有剥离任何 ../.. (不是它应该,但似乎也没有任何替代方案)所以你可能必须添加“假”目录才能使您的文件构建在“正确”目录中。例如,我有 $(IntDir)/a/a/%(RelativeDir)/ 只是因为它可以在 $(IntDir) 中构建,因为我的 .cpp 路径中有两个 ../ (路径相对于 $(ProjectDir ), 我想)。另请注意,%(RelativeDir) 带有 % 而 $(IntDir) 带有 $(答案是正确的,只是通过快速阅读,可能会错过这个事实)。
        • 嗯...我想知道为什么默认情况下没有设置。好吧,我想我会把它添加到每个项目中(如果没有这个修复,几乎没有任何东西可以编译)
        • 这在 Visual Studio 2012 更新 1 中有效,但由于我修补到更新 4,VS 似乎不想再为目标文件创建中间目录。 :((见stackoverflow.com/questions/30212698.
        • 我在CLI中使用cl.exe怎么办?
        【解决方案6】:

        我曾经在同一个项目中拥有 .c.cpp 文件,它们具有相同的文件名。这些文件到处都是文件夹,其他人提供的解决方案造成了混乱,文件夹地狱(在我的情况下)。即使是 Release 构建也会覆盖 Debug 构建!

        一个好的(不是完美的)解决方案是使用 $(ParentName),但由于某些人无法理解的原因,它已从更高版本的 Visual Studio (2015+) 中删除。

        我现在成功使用的是: $(IntDir)%(文件名)%(扩展名).obj

        至少将 .c 构建的目标文件与 .cpp 分开。

        【讨论】:

          【解决方案7】:

          我遇到了与链接器警告类似的问题LNK4042:对象指定了不止一次;额外内容被忽略。在我的例子中,Visual Studio 试图编译具有相同名称的头文件和源文件 - MyClass.hMyClass.cpp。发生这种情况是因为我将 .cpp 文件重命名为 .h 并且 Visual Studio 感到困惑。通过查看Debug 目录中的编译器日志,我注意到了这个问题。要解决,只需从项目中删除 .h 文件,然后重新添加即可。

          【讨论】:

          • 感谢您发布此信息!旧的删除文件并将其添加回例程也对我有用。我真的开始把头撞到墙上了。
          • 谢谢@AndreyLevichev——这个回复也为我解决了这个问题。在项目文件中很清楚 .h 文件位于“ClCompile”组而不是“ClInclude”组中
          • 或者您可以在解决方案资源管理器中右键单击foo.h 文件并将“项目类型”设置为“C/C++ 标头”而不是“C/C++ 编译器”。
          • 为此 +1。如果我没有看到你的评论,我永远不会发现我的问题。
          • @Yaur - 或者更好的是,将其更改为 CLInclude 条目
          【解决方案8】:

          我在 C/C++ -> Output Files -> "Object File Name" 下使用 $(IntDir)\%(Directory)\。

          【讨论】:

          • 虽然与公认的答案基本相同,但使用 %(Directory) 而不是 %(RelativeDir) 更安全一些。正如 n1ckp 在接受的答案 cmets 中指出的那样,根据您的项目在磁盘上的结构,相对目录可能最终会将您的 .obj 文件放在意想不到的地方。
          【解决方案9】:

          我在 stdafx.cpp 中遇到了这个问题。不知何故,stdafx.cpp 被复制了,所以有第二个 StdAfx.cpp(注意不同的情况)。

          删除 StdAfx.cpp 后一切正常!

          使用 VS 2010。

          【讨论】:

          • 有一个类似的问题,但不是文件被复制,而是同一个文件在 ClCompile ItemGroup 中列出了两次。
          【解决方案10】:

          在解决方案资源管理器窗口、属性、C/C++、输出文件、对象文件名设置中右键单击 .cpp 文件。默认是$(IntDir)\,这就是扁平化的作用。所有 .obj 文件都将进入调试配置中的“调试”目录 $(IntDir)。

          您可以更改设置,例如$(IntDir)\is2.obj。或者从一组中选择所有文件(使用 Shift+单击)并将设置更改为,例如,$(IntDir)\identity\

          或者您可以更改 .cpp 文件名,以便 .obj 文件不会相互覆盖。在两个目录中拥有完全相同名称的文件有点奇怪。

          或者您可以创建多个项目,例如为身份和范围中的文件创建 .lib 项目。例如,通常在 makefile 项目中完成。但是,除非您使用项目属性表,否则这确实会使管理编译和链接设置更加麻烦。

          【讨论】:

          • 谢谢,我已经重命名了这些文件,因为这样做更容易。有没有办法要求 Visual 保留我在项目中精心构建的层次结构?我知道多个文件具有相同的文件名很奇怪,但我更喜欢通过子目录而不是为我的文件添加前缀...而且将它们放在子目录中并以子目录名称作为前缀是多余的!
          • 您可以同时更改多个文件的设置。在单击以选择它们的同时按住 CTRL 键。上次我尝试使用 `$(IntDir)\$(ParentName)` 很麻烦。
          • @Hans:我想我会继续使用不同的名称,我对解决方案不太满意,但由于它仅用于单元测试部分,我想我会接受它。跨度>
          • 是否可以在属性表中为每个文件设置$(IntDir)?我知道你可以在属性表中为整个项目设置它,但我不知道你是否可以根据正在编译的文件的路径来设置它。 (我的猜测是否定的,但我是一个完整的 MSBuild 菜鸟)
          • @James,项目属性表具有项目范围,它们会影响所有文件。
          猜你喜欢
          • 2012-07-02
          • 1970-01-01
          • 2012-02-27
          • 2012-03-04
          • 2011-12-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-29
          相关资源
          最近更新 更多