web-dev-qa-db-ja.com

`WinMain @ 16 'への未定義の参照

Eclipse CDTを使用してプログラムをビルドしようとすると、次のメッセージが表示されます。

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

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

99
Simplicity

次の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 "^ subsystem" 
 Subsystem 00000003(Windows CUI)
 
 C:\ test> _ 

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

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

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

 C:\ test> gnuc x.cpp -mwindows 
 
 C:\ test> objdump -x a.exe | findstr/i "^ subsystem" 
 Subsystem 00000002(Windows GUI)
 
 C:\ test> _ 

-mwindowsフラグはまだ半文書化されていますが、これでうまくいくことを願っています。

その半文書化されたフラグなしでビルドすると、リンカに希望するサブシステム値をより具体的に伝える必要があり、いくつかのWindows APIインポートライブラリは一般に明示的に指定する必要があります。

 C:\ test> gnuc x.cpp -Wl、-subsystem、windows 
 
 C:\ test> objdump -x a.exe | findstr/i "^ subsystem" 
 Subsystem 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 "サブシステム"を見つける| find/i "Windows" 
 3サブシステム(Windows CUI)
 
 C:\ test> _ 

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

 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のリンカーは、ランタイムライブラリエントリポイントを使用します。これは、winMainCRTStartupと呼ばれる、Microsoftの非標準WinMain標準のmainの代わりに。

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

する必要があるのは、使用するエントリポイント、つまり標準のmainCRTStartupを呼び出すmainをMicrosoftのリンカーに伝えることだけです。

 C:\ test> msvc x.cpp user32.lib/link/subsystem:windows/entry:mainCRTStartup 
 x.cpp 
 
 C:\ test> dumpbin/headers x.exe |/i "サブシステム"を見つける| find/i "Windows" 
 2サブシステム(Windows GUI)
 
 C:\ test> _ 

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

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

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

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

さて、あなたはおそらくmissingmainです。そして、おそらく(適切な)WinMainもありません!そして、g ++は、main(そのようなものはない)、およびMicrosoftの非標準のWinMain(そのようなものはない)を検索した後、後者が見つからないと報告します。

空のソースでテストする:

 C:\ test> type 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):undefined referen 
 ce to `WinMain @ 16 '
 collect2:ldが1つの終了ステータスを返しました
 
 C:\ test> _ 
169

Cheers and hthによる上記の投稿を要約します。 -アルフ、main()またはWinMain()が定義されていることを確認してください。g++は正しいことを行う必要があります。

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

61
Tim Ludwinski

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

25
X-Frox

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

--Cプロジェクトをビルドするときに同様の問題があった

1
JabbaJava