`WinMain @ 16 '에 대한 정의되지 않은 참조


110

를 사용하여 프로그램을 빌드하려고 Eclipse CDT하면 다음과 같은 결과가 나타납니다.

/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106) :`WinMain @ 16에 대한 정의되지 않은 참조

왜 그런 겁니까? 그리고이 문제를 어떻게 해결할 수 있습니까?

답변:


184

다음 Windows API 수준 프로그램을 고려하십시오.

#define NOMINMAX
#include <windows.h>

int main()
{
    MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}

이제 특별한 옵션없이 GNU 도구 모음 (예 : g ++)을 사용하여 빌드 해 보겠습니다. 여기 gnuc에 제가 사용하는 배치 파일이 있습니다. g ++를 더 표준으로 만드는 옵션 만 제공합니다.

C : \ test> gnuc x.cpp

C : \ test> objdump -x a.exe | findstr / i "^ 하위 시스템"
하위 시스템 00000003 (Windows CUI)

C : \ 테스트> _

이는 링커가 기본적으로 콘솔 하위 시스템 실행 파일을 생성했음을 의미합니다 . 파일 헤더 의 하위 시스템 값은 프로그램에 필요한 서비스를 Windows에 알려줍니다. 이 경우 콘솔 시스템에서는 프로그램에 콘솔 창이 필요합니다.

이것은 또한 명령 인터프리터가 프로그램이 완료 될 때까지 기다리게합니다.

이제 GUI 하위 시스템으로 빌드 해 보겠습니다 . 이는 프로그램에 콘솔 창이 필요하지 않음을 의미합니다.

C : \ test> gnuc x.cpp -mwindows

C : \ test> objdump -x a.exe | findstr / i "^ 하위 시스템"
하위 시스템 00000002 (Windows GUI)

C : \ 테스트> _

-mwindows플래그가 반 문서화 되었지만 지금까지는 괜찮습니다 .

반 문서화 된 플래그없이 빌드하려면 링커에게 원하는 하위 시스템 값을 더 구체적으로 알려야하며 일부 Windows API 가져 오기 라이브러리는 일반적으로 명시 적으로 지정해야합니다.

C : \ test> gnuc x.cpp -Wl, -subsystem, windows

C : \ test> objdump -x a.exe | findstr / i "^ 하위 시스템"
하위 시스템 00000002 (Windows GUI)

C : \ 테스트> _

GNU 툴체인에서는 잘 작동했습니다.

그러나 Microsoft 도구 체인, 즉 Visual C ++는 어떻습니까?

음, 콘솔 하위 시스템 실행 파일로 빌드하면 잘 작동합니다.

C : \ test> msvc x.cpp user32.lib
x.cpp

C : \ test> dumpbin / headers x.exe | / i "서브 시스템"찾기 | / i "Windows"찾기
               3 하위 시스템 (Windows CUI)

C : \ 테스트> _

그러나 Microsoft의 도구 모음을 GUI 하위 시스템으로 구축하면 기본적으로 작동하지 않습니다.

C : \ test> msvc x.cpp user32.lib / link / subsystem : windows
x.cpp
LIBCMT.lib (wincrt0.obj) : 오류 LNK2019 : ___tmainCRTStartu 함수에서 참조 된 해결되지 않은 외부 기호 _WinMain @ 16
피
x.exe : 치명적인 오류 LNK1120 : 해결되지 않은 외부 1 개

C : \ 테스트> _

기술적으로 이것은 Microsoft의 링커 가 GUI 하위 시스템에 대해 기본적으로 비표준 이기 때문 입니다. 기본적으로 하위 시스템이 GUI 인 경우 Microsoft의 링커는 표준 대신 Microsoft의 비표준을 호출 하는 기계 코드 실행이 시작되는 함수 인 런타임 라이브러리 진입 점을 사용합니다 .winMainCRTStartupWinMainmain

그러나 그것을 고치는 데 큰 문제는 없습니다.

당신이해야 할 일은 마이크로 소프트 링커에게 어떤 진입 점을 사용할 mainCRTStartup것인지 , 즉 표준을 호출 하는를 알려주 는 것입니다 main.

C : \ test> msvc x.cpp user32.lib / link / subsystem : windows / entry : mainCRTStartup
x.cpp

C : \ test> dumpbin / headers x.exe | / i "서브 시스템"찾기 | / i "Windows"찾기
               2 하위 시스템 (Windows GUI)

C : \ 테스트> _

문제 없지만 매우 지루합니다. 그리고 대부분 Microsoft의 비표준 기본 도구 만 사용하는 대부분의 Windows 프로그래머는 이에 대해 알지 못하며 Windows GUI 하위 시스템 프로그램이 표준이 아닌 비표준 프로그램을 "반드시"가져야한다고 잘못 생각하고 WinMain있습니다. main. 지나가는 과정에서 C ++ 0x를 사용하면 컴파일러가 독립형인지 호스팅되는지 (호스팅 될 때 표준을 지원해야 함 main) 광고해야하기 때문에이 문제가 발생합니다 .

어쨌든 이것이 g ++ WinMain 누락 에 대해 불평 할 수 있는 이유입니다 . 이것은 GUI 하위 시스템 프로그램에 대해 Microsoft 도구가 기본적으로 필요로하는 어리석은 비표준 시작 기능입니다.

그러나 위에서 볼 수 있듯이 g ++는 mainGUI 하위 시스템 프로그램에서도 표준에 문제가 없습니다 .

그렇다면 무엇이 문제일까요?

글쎄, 당신은 아마 없는main. 그리고 당신은 (적절한) WinMain것도 없을 것입니다 ! 그런 다음 g ++는 main(그렇지 않음) 및 Microsoft의 비표준 WinMain( 그렇지 않음) 을 검색 한 후 후자가 누락되었다고보고합니다.

빈 소스로 테스트 :

C : \ test> 유형 nul> y.cpp

C : \ test> gnuc y.cpp -mwindows
c : / program files / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o) : main.c :(. text + 0xd2 ) : 정의되지 않은 참조
ce-`WinMain @ 16 '
collect2 : ld가 1 종료 상태를 리턴했습니다.

C : \ 테스트> _

3
@Alf P. Steinbach. 귀하의 좋은 답변에 감사드립니다. 에 관해서는 All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main. Eclipse CDT명령 줄을 사용하지 않기 때문에 그렇게하는 방법이 있습니까? 감사합니다
Simplicity 2011 년

1
@ user588855 : g ++를 사용하고 있으므로 (아마도) 적용되지 않습니다. (아마도) 끝에있는 부분 만 적용됩니다. 즉, 또는를 정의 main하거나 WinMain관련 파일이 프로젝트에 포함되어 있는지 확인하십시오. 건배,
건배와 hth. -Alf 2011 년

@Alf P. Steinbach. main또는 정의는 무엇을 의미 winmain합니까? 감사합니다
Simplicity 2011 년

1
코드가있는 main.cpp라는 파일을 방금 만들었습니다. int main () {}
Indeed

3
각 반대 투표자가 반대표를 설명 할 수 있다면 좋을 것입니다. 아마도 다른 독자들도 같은 오해를 가지고있을 것입니다 (무엇이든간에). 그러면 우리는 그것을 해결할 수 있습니다. 일부는 오도하는 대신 모든 사람이 이익을 얻을 것입니다. 그래서, 당신의 반대 투표를 설명하십시오. 감사합니다.
건배와 hth. - 알프

68

Cheers와 hth의 위 게시물을 요약합니다. -Alf, 당신이 가지고 main()있거나 WinMain()정의 했는지 확인 하고 g ++가 올바른 일을해야합니다.

내 문제는 그것이 main()실수로 네임 스페이스 내부에 정의 되었다는 것 입니다.


이 모든 것에 대해 중요한 것을 깨달았습니다. 제 경우에는 인수 (argc, argv)를 선언하지 않았기 때문에 main ()을 찾지 못했습니다. 추가되면 main을 찾았습니다. 또한 이것이 작동하는 방식의 특성은 mingw가 WinMain을 호출하는 자체 메인을 제공함으로써 도움을 주려고한다는 것을 의미합니다. GUI 프로그램에는 WinMain 만 있고 mingw의 기본 스텁이 사용됩니다. 메인이 있으면 대신 사용합니다.
Jeff Muir

extern "C"int main (void)이 문제를 해결했습니다.
dryler

33

SDL로 애플리케이션을 컴파일하는 동안이 오류가 발생했습니다. 이것은 SDL_main.h에서 자체 주 함수를 정의하는 SDL로 인해 발생했습니다. SDL이 주 함수를 정의하는 것을 방지하려면 SDL.h 헤더가 포함되기 전에 SDL_MAIN_HANDLED 매크로를 정의해야합니다.


좋은 대답입니다! +1
Mohammad Kanan

감사합니다! 이 명령은 작동합니다. gcc main.c -I "E : \ Libs \ SDL2-devel-2.0.12-mingw \ SDL2-2.0.12 \ i686-w64-mingw32 \ include"-I "E : \ Libs \ SDL2_ttf- devel-2.0.15-mingw \ SDL2_ttf-2.0.15 \ i686-w64-mingw32 \ include "-L"E : \ Libs \ SDL2-devel-2.0.12-mingw \ SDL2-2.0.12 \ i686-w64- mingw32 \ lib "-L"E : \ Libs \ SDL2_ttf-devel-2.0.15-mingw \ SDL2_ttf-2.0.15 \ i686-w64-mingw32 \ lib "-lSDL2 -lSDL2main -lSDL2_ttf -o
app.exe

5

빌드하기 전에 .c 파일을 저장하십시오. 컴퓨터가 파일 내부에 정보가없는 파일 경로를 참조하고 있다고 생각합니다.

--C 프로젝트를 빌드 할 때 비슷한 문제가 발생했습니다.


이것은 실제로 내 문제를 해결했으며 더 많은 관심을 끌 수 있도록이 댓글을 남깁니다.
David Chen

0

프로젝트에 모든 파일이 포함되어 있는지 확인하십시오.

cLion을 업데이트 한 후에도 동일한 오류가 발생했습니다. 몇 시간의 작업 끝에 내 파일 중 하나가 프로젝트 대상에 포함되지 않았 음을 알았습니다. 활성 프로젝트에 다시 추가 한 후 winmain16에 대한 정의되지 않은 참조를 가져 오는 것을 중지하고 코드를 컴파일했습니다.

편집 : IDE 내에서 빌드 설정을 확인하는 것도 가치가 있습니다.

(이 오류가 최근에 IDE를 업데이트 한 것과 관련이 있는지 확실하지 않습니다. 인과 관계 일 수도 있고 단순히 상관 관계 일 수도 있습니다. 해당 요소에 대한 통찰력을 자유롭게 언급하십시오!)

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