Visual Studio 2010의 이상한 "경고 LNK4042"


81

저는 Visual Studio 2010 (C ++)의 사소하지 않은 경고로 머리가 거의 맞지 않았습니다.

컴파일 결과는 다음과 같습니다.

1 Debug \ is.obj : 경고 LNK4042 : 개체가 두 번 이상 지정되었습니다. 추가 무시 됨
1 Debug \ make.obj : 경고 LNK4042 : 개체가 두 번 이상 지정되었습니다. 추가 항목 무시 됨
1 Debug \ view.obj : 경고 LNK4042 : 개체가 두 번 이상 지정되었습니다. extras ignore
1 identity.obj : error LNK2019 : unresolved external symbol void __cdecl test::identity::view(void)(? view @ identity @ test @@ YAXXZ) referenced in function void __cdecl test::identity::identity(void)(? identity @ 0test @@ YAXXZ)
1 identity.obj : error LNK2019 : unresolved external symbol void __cdecl test::identity::make(void)(? make @ identity @ test @@ YAXXZ) 함수에서 참조 됨 void __cdecl test::identity::identity(void)(? identity @ 0test @@ YAXXZ)
1 range.obj : 오류 LNK2019 : void __cdecl test::range::is(void)함수 void __cdecl test::range::range(void)(? range @ 0test 에서 참조되는 해결되지 않은 외부 기호 (? is @ range @ test @@ YAXXZ) @@ 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가 파일 계층 구조를 평면화하지 않도록하는 방법이 있습니까?


3
똑같은 일이 생겼는데, 우리가 수동으로 "고쳐야"한다는 사실이 정말 짜증납니다. 나보다 먼저 물어봐서 기뻐. :)
GManNickG 2011 년

5
나는 오래 전에 SO 검색을 포기했습니다. :) Google.
GManNickG 2011 년

38
방금 VS 2013에서 비슷한 문제를 해결했습니다. 저에게 문제는 헤더 파일이 독립 실행 형 C ++ 파일 인 것처럼 컴파일된다는 것입니다. 그래서 나는 foo.cpp와 foo.h에 대한 하나의 동일한 이름을 가진 두 개의 객체 파일을 얻었습니다. 해결책은 foo.h에 대한 적절한 페이지로 이동하여 구성 속성-> 일반-> 항목 유형을 "C / C ++ 헤더"로 변경하고 클린 빌드를 수행하는 것이 었습니다.
Adrian McCarthy

1
@AdrianMcCarthy 나는 같은 문제가 있었고 귀하의 제안으로 해결되었습니다.
trenki

1
@AdrianMcCarthy의 의견이 해결책입니다. 파일의 항목 유형을 자동으로 설정하는 추가-> "새 항목"마법사 때문이어야합니다.
Dustin Biser

답변:


99

전체 프로젝트의 속성을 열고 값을 C/C++ -> Output Files -> "Object File Name"다음 과 같이 변경하면 대답이라고 생각되는 내용을 교차 게시하고 싶었습니다 .

$ (IntDir) / % (RelativeDir) /

VS 2010에서 나는 이것이 모든 개체 파일을 명확하게 할 것이라고 믿습니다 (창이 어떤 미친 상황에서도 같은 디렉토리에 같은 이름을 가진 두 개의 파일을 가질 수 없다고 믿기 때문에). 여기 에서 자세한 내용도 확인 하십시오 .


아! 이제 뭔가 내가 최대한 빨리 집에 돌아으로 시도해야한다는 점 : D
마티유 M.

7
추가하기 만하면됩니다. % (RelativeDir)가 경로에서 ../ ..을 제거하지 않는 것 같으므로 "가짜"디렉토리를 추가해야 할 수도 있습니다. 파일이 "올바른"디렉토리에 빌드되도록합니다. 예를 들어, $ (IntDir) / a / a / % (RelativeDir) / 내 .cpp 경로에 두 개의 ../ 때문에 $ (IntDir)에서 빌드 할 수 있습니다 (경로는 $ (ProjectDir) ), 나는 생각한다). 또한 % (RelativeDir)에는 %가 있고 $ (IntDir)에는 $가 있습니다 (답은 정확합니다. 빨리 읽으면 그 사실을 놓칠 수 있습니다).
n1ckp

2
흠 ... 왜 이것이 기본적으로 설정되어 있지 않은지 궁금합니다. 글쎄, 나는 이것을 모든 프로젝트에 추가 할 것이라고 생각한다. (이 수정 없이는 거의 컴파일되지 않는다)
Navin

이것은 Visual Studio 2012 업데이트 1에서 작동했지만 업데이트 4로 패치했기 때문에 VS는 더 이상 개체 파일에 대한 중간 디렉터리를 만들고 싶지 않은 것 같습니다. :( ( stackoverflow.com/questions/30212698 참조 . )
Thomas Young

cl.exeCLI에서 사용하는 방법은 무엇입니까?
학습

145

링커 경고 LNK4042 와 비슷한 문제가 발생했습니다 . 개체가 두 번 이상 지정되었습니다. 추가 항목은 무시 됩니다. 내 경우에는 Visual Studio에서 같은 이름을 가진 두 헤더 및 소스 파일을 컴파일하려고했다 - MyClass.hMyClass.cpp. .cpp파일 이름을로 바꾸고 .hVisual Studio가 혼란스러워서 발생했습니다. Debug디렉토리 의 컴파일러 로그를보고 문제를 발견했습니다 . 해결하려면 .h프로젝트에서 파일을 제거한 다음 다시 추가하십시오.


2
이것을 게시 해 주셔서 감사합니다! 이전 파일을 제거하고 다시 루틴을 추가하면 나에게도 트릭이 생겼습니다. 나는 정말로 이것을 벽에 내 머리를 두드리기 시작했다.
Wes

3
@AndreyLevichev에게 감사드립니다.이 응답은 저에게도 문제를 해결했습니다. 프로젝트 파일에서 .h 파일이 "ClInclude"그룹 대신 "ClCompile"그룹에 있다는 것이 매우 분명합니다
jglouie

35
또는 foo.h솔루션 탐색기에서 파일을 마우스 오른쪽 단추로 클릭 하고 "항목 유형"을 "C / C ++ 컴파일러"가 아닌 "C / C ++ 헤더"로 설정할 수 있습니다.
Thomas Eding 2012-06-07

이것에 대해 +1. 귀하의 의견을 보지 못했다면 내 문제를 발견하지 못했을 것입니다.
crocboy

2
@Yaur-아니면 더 나은 CLInclude항목으로 변경하십시오
TED

8

솔루션 탐색기 창, 속성, C / C ++, 출력 파일, 개체 파일 이름 설정에서 .cpp 파일을 마우스 오른쪽 단추로 클릭합니다. 기본값은 $(IntDir)\입니다. 이것이 병합을 수행하는 것입니다. 모든 .obj 파일은 디버그 구성의 "Debug"디렉토리 인 $ (IntDir)로 이동합니다.

설정을 변경할 수 있습니다 $(IntDir)\is2.obj. 또는 한 그룹에서 모든 파일을 선택하고 (Shift + 클릭 사용) 설정을 다음과 같이 변경합니다.$(IntDir)\identity\

또는 .obj 파일이 서로 덮어 쓰지 않도록 .cpp 파일 이름을 변경할 수 있습니다. 두 디렉토리에 정확히 같은 이름의 파일을 갖는 것은 약간 이상합니다.

또는 ID 및 범위의 파일에 대해 .lib 프로젝트를 만드는 등 여러 프로젝트를 만들 수 있습니다. 예를 들어 일반적으로 메이크 파일 프로젝트에서 수행됩니다. 그러나 프로젝트 속성 시트를 사용하지 않는 한 컴파일 및 링크 설정을 관리하는 것이 더 번거 롭습니다.


고맙습니다. 더 쉬운 방법이어서 이미 파일 이름을 변경했습니다. Visual에 프로젝트에서 신중하게 구축 한 계층 구조를 유지하도록 요청할 수있는 방법이 없습니까? 여러 파일에 대해 동일한 파일 이름을 갖는 것이 이상하다는 것을 알고 있지만 파일 접두사보다는 하위 디렉터리별로 클러스터링하는 것을 선호합니다 ... 그리고 하위 디렉터리에 파일을 넣고 하위 디렉터리 이름으로 접두사를 붙이는 것이 중복됩니다!
Matthieu M.

여러 파일에 대한 설정을 동시에 변경할 수 있습니다. Ctrl 키를 누른 채 클릭하여 선택합니다. 마지막으로 시도했을 때`$ (IntDir) \ $ (ParentName)`을 사용하는 것이 문제였습니다.
Hans Passant

@Hans : 다른 이름을 계속 사용할 것 같네요. 해결책에별로 만족 스럽지는 않지만 단위 테스트 부분에만 해당하므로 함께 살 것 같아요.
Matthieu M.

$(IntDir)속성 시트에서 파일별로 설정할 수 있습니까? 속성 시트에서 전체 프로젝트에 대해 설정할 수 있다는 것을 알고 있지만 컴파일되는 파일의 경로를 기반으로 설정할 수 있는지 여부는 모르겠습니다. (내 생각에는 없지만, 나는 완전한 MSBuild를 멍청한 놈이야)
제임스 McNellis

@James, 프로젝트 속성 시트에는 프로젝트 범위가 있으며 모든 파일에 영향을 미칩니다.
Hans Passant

7

헤더 파일-> 속성-> 항목 유형을 마우스 오른쪽 버튼으로 클릭합니다 ( C / C ++ 헤더 선택 ). Cpp 파일과 동일하게 수행하지만 C / C ++ 컴파일러를 선택하십시오 (나에게 적합합니다)


이것이 제가 찾고자하는 마지막 생각이었습니다. 감사합니다.
McLeary 2011

4

C / C ++-> 출력 파일-> "개체 파일 이름"에서 $ (IntDir) \ % (Directory) \를 사용합니다.


본질적으로 받아 들여지는 대답과 동일하지만 % (RelativeDir) 대신 % (Directory)를 사용하는 것이 조금 더 안전합니다. 허용되는 답변 주석에서 n1ckp가 언급했듯이 프로젝트가 디스크에서 얼마나 정확하게 구조화되어 있는지에 따라 상대 디렉토리가 예기치 않은 위치에 .obj 파일을 배치 할 수 있습니다.
user1593842

4

새 파일을 삭제하고 만드는 대신 컴파일 / 포함 설정을 변경할 수 있습니다.

project.vcxproj 파일로 이동하여 편집기로 열고 html과 같은 줄을 찾으십시오 <ItemGroup>.

다음과 같이 표시되어야합니다.

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

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

구현 파일이 .cpp이고 선언이 .hpp라고 가정합니다. 모든 구현 파일이 하나 이상있는 경우 첫 번째 섹션 사이에 나열되고 여러 선언 파일의 두 번째 섹션에 대해서도 마찬가지로 나열되는지 확인하십시오.


3

stdafx.cpp 에서이 문제가 발생했습니다. 어떻게 든 stdafx.cpp가 복제되었으므로 두 번째 StdAfx.cpp가 있습니다 (다른 경우에 유의하십시오).

StdAfx.cpp를 제거한 후 모든 것이 잘 작동했습니다!

VS 2010 사용.


비슷한 문제가 있었지만 파일이 복제되는 대신 ClCompile ItemGroup에 두 번 나열된 동일한 파일이었습니다.
Nicholas Betsworth 2015 년

2

나는 같은 프로젝트 .c.cpp 파일 에 동일한 파일 이름을 사용했습니다 . 파일은 사방의 폴더에 있었고 다른 사람들이 제공 한 솔루션은 엉망이었고 폴더 지옥 (제 경우)을 만들었습니다. 릴리스 빌드 조차도 디버그 빌드를 덮어 씁니다 !

좋은 (완벽하지 않은) 솔루션은 $ (ParentName)을 사용하는 것이지만, 어떤 이유로 든 Visual Studio의 이후 버전 (2015+)에서 제거되었습니다.

지금 성공적으로 사용하는 것은 $ (IntDir) % (Filename) % (Extension) .obj입니다.

적어도 .c 빌드 된 오브젝트 파일을 .cpp 에서 분리 합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.