Visual Studio 2010的奇怪“警告LNK4042”

时间:2010-09-12 14:24:14

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

我刚刚被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::view(void)中引用的未解析的外部符号void __cdecl test::identity::identity(void)(?view @ identity @ test @@ YAXXZ)(?identity @ 0test @@ YAXXZ)
  1 identity.obj:错误LNK2019:函数void __cdecl test::identity::make(void)中引用的未解析外部符号void __cdecl test::identity::identity(void)(?make @ identity @ test @@ YAXXZ)(?identity @ 0test @@ YAXXZ)
  1 range.obj:错误LNK2019:函数void __cdecl test::range::is(void)中引用的未解析的外部符号void __cdecl test::range::range(void)(?是@ range @ test @@ YAXXZ)(?range @ 0test @@ 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不展平文件层次结构?

9 个答案:

答案 0 :(得分:127)

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

答案 1 :(得分:93)

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

$(IntDir)/%(RelativeDir)/

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

答案 2 :(得分:8)

右键单击“解决方案资源管理器”窗口中的.cpp文件,“属性”,“C / C ++”,“输出文件”,“对象文件名”设置。默认值为$(IntDir)\,即执行展平的内容。所有.obj文件都将进入$(IntDir),调试配置中的“Debug”目录。

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

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

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

答案 3 :(得分:5)

右键点击标题文件 - >财产 - > ItemType(选择C / C ++标题)。对Cpp文件做同样的事情,但选择C / C ++ COmpiler(这对我有用)

答案 4 :(得分:4)

我在C / C ++下使用$(IntDir)\%(目录)\ - >输出文件 - > “对象文件名”。

答案 5 :(得分:3)

我有stdafx.cpp这个问题。某种程度上stdafx.cpp得到了重复,所以还有第二个StdAfx.cpp(请注意不同的情况)。

删除StdAfx.cpp后一切正常!

使用VS 2010。

答案 6 :(得分:3)

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

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

它应该类似于:

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

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

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

答案 7 :(得分:2)

我曾经在同一个项目 .c .cpp 文件中使用相同的文件名。文件存放在整个文件夹中,其他人提供的解决方案造成了混乱,文件夹地狱(在我的情况下)。即使发布版本也会覆盖调试版本!

一个好的(不完美的)解决方案是使用$(ParentName),但出于某种原因,除了任何人的掌握之外,它已从Visual Studio(2015 +)的更高版本中删除。

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

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

答案 8 :(得分:0)

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

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