「WinMain @ 16」への未定義の参照


110

を使用してプログラムをビルドしようとするとEclipse CDT、次のようになります。

/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): `WinMain @ 16への未定義の参照

何故ですか?そして、どうすればこの問題を解決できますか?

回答:


183

次の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:\ test> _

これは、リンカがデフォルトで実行可能なコンソールサブシステムを生成したことを意味します。ファイルヘッダーのサブシステム値は、プログラムに必要なサービスをWindowsに通知します。この場合、コンソールシステムでは、プログラムにコンソールウィンドウが必要です。

これにより、コマンドインタープリターはプログラムが完了するまで待機します。

次に、GUIサブシステム使用してビルドします。これは、プログラムがコンソールウィンドウを必要としないことを意味します。

C:\ test> gnuc x.cpp -mwindows

C:\ test> objdump -x a.exe | findstr / i "^サブシステム"
サブシステム00000002(Windows GUI)

C:\ test> _

-mwindowsフラグは半文書化されているだけですが、うまくいけばこれまでのところ問題ありません。

セミドキュメント化されたフラグなしでビルドする場合は、必要なサブシステム値をリンカーに具体的に通知する必要があります。その場合、一部のWindows APIインポートライブラリは、一般的に明示的に指定する必要があります。

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

C:\ test> objdump -x a.exe | findstr / i "^サブシステム"
サブシステム00000002(Windows GUI)

C:\ test> _

これは、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:\ test> _

ただし、GUIサブシステムとしてのMicrosoftのツールチェーンの構築では、デフォルトでは機能しません。

C:\ test> msvc x.cpp user32.lib / link / subsystem:windows
x.cpp
LIBCMT.lib(wincrt0.obj):エラーLNK2019:未解決の外部シンボル_WinMain @ 16が関数___tmainCRTStartuで参照されています
p
x.exe:致命的なエラーLNK1120:1つの未解決の外部

C:\ test> _

技術的には、MicrosoftのリンカーはGUIサブシステムのデフォルトでは非標準であるためです。デフォルトでは、サブシステムはGUIが、あるときに、Microsoftのリンカは、ランタイムライブラリの使用エントリー・ポイント、マシンコードの実行を開始するには、呼び出される関数winMainCRTStartupMicrosoftの非標準呼び出して、WinMain代わりに標準のをmain

しかし、それを修正するのは大したことではありません。

あなたがしなければならないのは、Microsoftのリンカーにどのエントリーポイントを使用するか、つまり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:\ test> _

問題ありませんが、とても退屈です。また、難解で隠されているため、ほとんどの場合Microsoftのデフォルトではない非標準ツールを使用するほとんどのWindowsプログラマーは、それについてさえ知らず、Windows GUIサブシステムプログラムは標準ではWinMainなく非標準である必要があると誤って考えています。main。ちなみに、コンパイラはC ++ 0xでこれに問題があります。コンパイラは、それが自立型かホスト型かを宣伝する必要があるためです(ホスト型の場合、標準をサポートする必要がありますmain)。

とにかく、それがg ++ WinMain欠落について文句を言う理由です。これは、MicrosoftのツールがデフォルトでGUIサブシステムプログラムに必要とする愚かな非標準の起動関数です。

ただし、上記のように、mainGUIサブシステムプログラムであっても、g ++は標準で問題ありません。

では、何が問題になるのでしょうか?

まあ、あなたはおそらく欠落していmainます。そしておそらくあなたも(適切な)何も持っていませんWinMain!そして、g ++はmain(そのような)を検索した後、およびMicrosoftの非標準WinMain(そのような)を検索した後、後者が欠落していると報告します。

空のソースを使用したテスト:

C:\ test>タイプnul> y.cpp

C:\ test> gnuc y.cpp -mwindows
c:/プログラムファイル/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2 ):未定義の参照
「WinMain @ 16」にCE
collect2:ldが1つの終了ステータスを返しました

C:\ test> _

3
@アルフ・P・シュタインバッハ。素敵な返事をありがとう。についてはAll you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard mainEclipse CDTコマンドラインを使用していないので、それを行う方法はありますか?ありがとう
シンプル

1
@ user588855:g ++を使用しているため、(おそらく)適用されません。最後の部分だけが(おそらく)適用されます。つまり、mainまたはを定義するかWinMain、関連ファイルがプロジェクトに含まれていることを確認します。乾杯、
乾杯とhth。-Alf

@アルフ・P・シュタインバッハ。mainまたはを定義するとはどういう意味winmainですか?ありがとう
シンプルさ

1
次のコードを含むmain.cppというファイルを作成しました:int main(){}
確かに

3
それぞれの反対投票者が反対投票を説明できればいいのですが。おそらく他の読者も同じ誤解(それが何であれ)を持っているので、それを明らかにすることができます。一部は誤解されるのではなく、誰もが利益を得ます。だから、あなたの反対票を説明してください。ありがとうございました。
乾杯とhth。-Alf

68

Cheersとhthによる上記の投稿をまとめます。-Alf、あなたが持っているmain()WinMain()定義していることを確認してください、そしてg ++は正しいことをするべきです。

私の問題は、それmain()が名前空間の中で誤って定義されたことでした。


このすべてについて重要なことに気づきました。私の場合、引数(argc、argv)を宣言していないため、main()が見つかりませんでした。追加すると、メインが見つかりました。また、これがどのように機能するかという性質は、mingwがWinMainを呼び出す独自のメインを提供することで支援しようとしていることを意味します。GUIプログラムはWinMainのみを持ち、mingwのメインスタブを使用してそこに到達します。メインがある場合は、代わりにメインを使用します。
Jeff Muir 2016年

extern "C" int main(void)で問題が解決しました
dryler

33

SDLでアプリケーションをコンパイルしているときにこのエラーが発生しました。これは、SDLがSDL_main.hに独自のメイン関数を定義しているために発生しました。SDLがメイン関数を定義しないようにするには、SDL.hヘッダーが含まれる前にSDL_MAIN_HANDLEDマクロを定義する必要があります。


正解です。+1
モハマドカナン

どうもありがとう!このコマンドは機能します: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
8Observer8

5

ビルドする前に.cファイルを保存してみてください。私はあなたのコンピュータがその中に情報のないファイルへのパスを参照していると思います。

-Cプロジェクトのビルド時に同様の問題がありました


これで実際に私の問題は解決しました。このコメントを残して、注目を集められるようにします。
David Chen

0

すべてのファイルがプロジェクトに含まれていることを確認します。

cLionを更新した後、同じエラーがポップアップ表示されました。何時間もいじくり回した後、自分のファイルの1つがプロジェクトターゲットに含まれていないことに気付きました。アクティブなプロジェクトに再度追加した後、未定義のwinmain16への参照の取得を停止し、コードをコンパイルしました。

編集:IDE内でビルド設定を確認することも価値があります。

(このエラーが最近IDEを更新したことに関連しているかどうかは不明です-原因であるか、単に相関している可能性があります。その要因についての洞察を自由にコメントしてください!)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.