Wenn ich versuche, ein Programm mit zu erstellen Eclipse CDT
, erhalte ich Folgendes:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): undefinierter Verweis auf `WinMain @ 16
Warum ist das so? Und wie kann ich dieses Problem lösen?
Wenn ich versuche, ein Programm mit zu erstellen Eclipse CDT
, erhalte ich Folgendes:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): undefinierter Verweis auf `WinMain @ 16
Warum ist das so? Und wie kann ich dieses Problem lösen?
Antworten:
Betrachten Sie das folgende Programm auf Windows-API-Ebene:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Jetzt erstellen wir es mit der GNU-Toolchain (dh g ++), ohne spezielle Optionen. Hiergnuc
ist nur eine Batch-Datei, die ich dafür verwende. Es bietet nur Optionen, um g ++ standardisierter zu machen:
C: \ test> gnuc x.cpp C: \ test> objdump -x a.exe | findstr / i "^ subsystem" Subsystem 00000003 (Windows CUI) C: \ test> _
Dies bedeutet, dass der Linker standardmäßig eine ausführbare Konsolensubsystemdatei erstellt hat . Der Subsystemwert im Dateikopf teilt Windows mit, welche Dienste das Programm benötigt. In diesem Fall benötigt das Programm beim Konsolensystem ein Konsolenfenster.
Dies führt auch dazu, dass der Befehlsinterpreter auf den Abschluss des Programms wartet.
Jetzt erstellen wir es mit dem GUI-Subsystem , was nur bedeutet, dass das Programm kein Konsolenfenster benötigt:
C: \ test> gnuc x.cpp -mwindows C: \ test> objdump -x a.exe | findstr / i "^ subsystem" Subsystem 00000002 (Windows-GUI) C: \ test> _
Hoffentlich ist das soweit in Ordnung, obwohl die -mwindows
Flagge nur halb dokumentiert ist.
Ohne dieses halbdokumentierte Flag müsste man dem Linker genauer mitteilen, welchen Subsystemwert er wünscht, und einige Windows-API-Importbibliotheken müssen dann im Allgemeinen explizit angegeben werden:
C: \ test> gnuc x.cpp -Wl, -subsystem, windows C: \ test> objdump -x a.exe | findstr / i "^ subsystem" Subsystem 00000002 (Windows-GUI) C: \ test> _
Mit der GNU-Toolchain hat das gut funktioniert.
Aber was ist mit der Microsoft-Toolchain, dh Visual C ++?
Das Erstellen als ausführbare Datei für ein Konsolensubsystem funktioniert einwandfrei:
C: \ test> msvc x.cpp user32.lib x.cpp C: \ test> dumpbin / headers x.exe | find / i "Subsystem" | find / i "Windows" 3 Subsystem (Windows CUI) C: \ test> _
Bei der Erstellung der Microsoft-Toolchain als GUI-Subsystem funktioniert dies jedoch nicht standardmäßig:
C: \ test> msvc x.cpp user32.lib / link / subsystem: windows x.cpp LIBCMT.lib (wincrt0.obj): Fehler LNK2019: ungelöstes externes Symbol _WinMain @ 16, auf das in der Funktion ___tmainCRTStartu verwiesen wird p x.exe: Schwerwiegender Fehler LNK1120: 1 ungelöste externe Daten C: \ test> _
Technisch gesehen liegt dies daran, dass der Linker von Microsoft für das GUI-Subsystem standardmäßig nicht dem Standard entspricht . Wenn das Subsystem eine grafische Benutzeroberfläche ist, verwendet der Linker von Microsoft standardmäßig einen Einstiegspunkt für die Laufzeitbibliothek , die Funktion, bei der die Ausführung des Maschinencodes beginnt. Diese Funktion winMainCRTStartup
ruft den Nicht-Standard WinMain
von Microsoft anstelle des Standards auf main
.
Keine große Sache, um das zu beheben.
Alles, was Sie tun müssen, ist dem Linker von Microsoft mitzuteilen, welcher Einstiegspunkt verwendet werden soll, nämlich mainCRTStartup
welcher Standardaufruf main
:
C: \ test> msvc x.cpp user32.lib / link / subsystem: windows / entry: mainCRTStartup x.cpp C: \ test> dumpbin / headers x.exe | find / i "Subsystem" | find / i "Windows" 2 Subsystem (Windows GUI) C: \ test> _
Kein Problem, aber sehr langweilig. Und so geheimnisvoll und verborgen, dass die meisten Windows-Programmierer, die meist nur die standardmäßig nicht standardmäßigen Tools von Microsoft verwenden, nicht einmal davon wissen und fälschlicherweise glauben, dass ein Windows-GUI-Subsystemprogramm nicht standardmäßig, WinMain
sondern standardmäßig sein muss main
. Im Übrigen wird Microsoft mit C ++ 0x ein Problem damit haben, da der Compiler dann bekannt geben muss, ob er freistehend oder gehostet ist (wenn er gehostet wird, muss er Standard unterstützen main
).
Dies ist der Grund, warum sich g ++ über das Fehlen beschweren kannWinMain
: Es ist eine alberne, nicht standardmäßige Startfunktion, die die Microsoft-Tools standardmäßig für GUI-Subsystemprogramme benötigen.
Wie Sie oben sehen können, hat g ++ main
selbst für ein GUI-Subsystemprogramm kein Problem mit dem Standard .
Was könnte das Problem sein?
Nun, Sie vermissen wahrscheinlich eine main
. Und Sie haben wahrscheinlich auch keine (richtige) WinMain
! Und dann meldet g ++ nach der Suche nach main
(kein solches) und nach Microsofts Nicht-Standard WinMain
(kein solches), dass letzteres fehlt.
Testen mit einer leeren Quelle:
C: \ test> Typ 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 ): undefinierte referen ce zu `WinMain @ 16 ' collect2: ld hat 1 Exit-Status zurückgegeben C: \ test> _
main
oder a WinMain
oder stellen Sie sicher, dass die entsprechende Datei im Projekt enthalten ist. Prost,
main
oder winmain
? Danke
Um den obigen Beitrag von Cheers und hth zusammenzufassen. - Alf, stellen Sie sicher, dass Sie haben main()
oder WinMain()
definiert haben und g ++ sollte das Richtige tun.
Mein Problem war, dass main()
es versehentlich in einem Namespace definiert wurde.
Beim Kompilieren meiner Anwendung mit SDL ist dieser Fehler aufgetreten. Dies wurde dadurch verursacht, dass SDL seine eigene Hauptfunktion in SDL_main.h definiert. Um zu verhindern, dass SDL die Hauptfunktion definiert, muss ein SDL_MAIN_HANDLED-Makro definiert werden, bevor der SDL.h-Header enthalten ist.
Versuchen Sie, Ihre .c-Datei vor dem Erstellen zu speichern. Ich glaube, Ihr Computer verweist auf einen Pfad zu einer Datei, in der sich keine Informationen befinden.
- Hatte ein ähnliches Problem beim Erstellen von C-Projekten
Überprüfen Sie, ob alle Dateien in Ihrem Projekt enthalten sind:
Nach der Aktualisierung von cLion wurde derselbe Fehler angezeigt. Nach stundenlangem Basteln bemerkte ich, dass eine meiner Dateien nicht im Projektziel enthalten war. Nachdem ich es wieder zum aktiven Projekt hinzugefügt hatte, wurde der undefinierte Verweis auf winmain16 nicht mehr abgerufen und der Code kompiliert.
Bearbeiten: Es lohnt sich auch, die Build-Einstellungen in Ihrer IDE zu überprüfen.
(Ich bin mir nicht sicher, ob dieser Fehler mit der kürzlich erfolgten Aktualisierung der IDE zusammenhängt - könnte kausal oder einfach korrelativ sein.
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
. Gibt es eine Möglichkeit, dies zu tun,Eclipse CDT
da ich die Befehlszeile nicht verwende? Danke