Quando provo a creare un programma utilizzando Eclipse CDT
, ottengo quanto segue:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): riferimento non definito a `WinMain @ 16
Perché? E come posso risolvere questo problema?
Quando provo a creare un programma utilizzando Eclipse CDT
, ottengo quanto segue:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): riferimento non definito a `WinMain @ 16
Perché? E come posso risolvere questo problema?
Risposte:
Considera il seguente programma a livello di API di Windows:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Ora costruiamolo usando la toolchain GNU (cioè g ++), senza opzioni speciali. Ecco gnuc
solo un file batch che utilizzo per questo. Fornisce solo opzioni per rendere g ++ più standard:
C: \ test> gnuc x.cpp C: \ test> objdump -x a.exe | findstr / i "^ sottosistema" Sottosistema 00000003 (Windows CUI) C: \ test> _
Ciò significa che il linker per impostazione predefinita ha prodotto un eseguibile del sottosistema della console . Il valore del sottosistema nell'intestazione del file indica a Windows quali servizi richiede il programma. In questo caso, con il sistema di console, il programma richiede una finestra di console.
Ciò fa sì che l'interprete dei comandi attenda anche il completamento del programma.
Ora costruiamolo con il sottosistema GUI , il che significa semplicemente che il programma non richiede una finestra della console:
C: \ test> gnuc x.cpp -mwindows C: \ test> objdump -x a.exe | findstr / i "^ sottosistema" Sottosistema 00000002 (GUI di Windows) C: \ test> _
Si spera che finora sia OK, anche se la -mwindows
bandiera è solo semi-documentata.
Costruendo senza quel flag semi-documentato si dovrebbe dire in modo più specifico al linker quale valore di sottosistema si desidera, e alcune librerie di importazione dell'API di Windows dovranno quindi in generale essere specificate esplicitamente:
C: \ test> gnuc x.cpp -Wl, -subsystem, windows C: \ test> objdump -x a.exe | findstr / i "^ sottosistema" Sottosistema 00000002 (GUI di Windows) C: \ test> _
Ha funzionato bene, con la toolchain GNU.
Ma per quanto riguarda la toolchain di Microsoft, ovvero Visual C ++?
Bene, la creazione di un eseguibile del sottosistema della console funziona bene:
C: \ test> msvc x.cpp user32.lib x.cpp C: \ test> dumpbin / headers x.exe | trova / i "sottosistema" | trova / i "Windows" 3 sottosistema (Windows CUI) C: \ test> _
Tuttavia, con la creazione della toolchain di Microsoft come sottosistema GUI non funziona per impostazione predefinita:
C: \ test> msvc x.cpp user32.lib / link / subsystem: windows x.cpp LIBCMT.lib (wincrt0.obj): errore LNK2019: simbolo esterno non risolto _WinMain @ 16 referenziato nella funzione ___tmainCRTStartu p x.exe: errore irreversibile LNK1120: 1 esterni non risolti C: \ test> _
Tecnicamente questo è perché il linker di Microsoft non è standard per impostazione predefinita per il sottosistema GUI . Per impostazione predefinita, quando il sottosistema è la GUI, il linker di Microsoft utilizza un punto di ingresso della libreria runtime , la funzione in cui inizia l'esecuzione del codice macchina, chiamata winMainCRTStartup
, che chiama Microsoft non standard WinMain
anziché standard main
.
Non è un grosso problema risolverlo, però.
Tutto quello che devi fare è dire al linker di Microsoft quale punto di ingresso utilizzare, vale a dire mainCRTStartup
, che chiama standard main
:
C: \ test> msvc x.cpp user32.lib / link / subsystem: windows / entry: mainCRTStartup x.cpp C: \ test> dumpbin / headers x.exe | trova / i "sottosistema" | trova / i "Windows" 2 sottosistema (GUI di Windows) C: \ test> _
Nessun problema, ma molto noioso. E così arcano e nascosto che la maggior parte dei programmatori Windows, che per lo più utilizzano solo strumenti Microsoft non standard per impostazione predefinita, non ne sono nemmeno a conoscenza e pensano erroneamente che un programma del sottosistema della GUI di Windows "debba" avere uno non standard WinMain
anziché uno standard main
. Per inciso, con C ++ 0x Microsoft avrà un problema con questo, poiché il compilatore deve quindi annunciare se è indipendente o ospitato (quando ospitato deve supportare lo standard main
).
Ad ogni modo, questo è il motivo per cui g ++ può lamentarsi della WinMain
mancanza: è una sciocca funzione di avvio non standard che gli strumenti di Microsoft richiedono per impostazione predefinita per i programmi del sottosistema della GUI.
Ma come puoi vedere sopra, g ++ non ha problemi con lo standard main
anche per un programma di sottosistema GUI.
Allora quale potrebbe essere il problema?
Beh, probabilmente ti manca un file main
. E probabilmente non ne hai neanche uno (corretto) WinMain
! E poi g ++, dopo aver cercato main
(no tale), e Microsoft non standard WinMain
(no tale), segnala che quest'ultimo manca.
Test con una fonte vuota:
C: \ test> digita nul> y.cpp C: \ test> gnuc y.cpp -mwindows c: / file di programma / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. text + 0xd2 ): referen non definito ce a "WinMain @ 16" collect2: ld ha restituito 1 stato di uscita C: \ test> _
main
o a WinMain
, o, assicurati che il file rilevante sia incluso nel progetto. Saluti,
main
o winmain
? Grazie
Per riassumere il post sopra di Cheers e hth. - Alf, assicurati di avere main()
o WinMain()
definito e g ++ dovrebbe fare la cosa giusta.
Il mio problema era che main()
era stato definito accidentalmente all'interno di uno spazio dei nomi.
Ho riscontrato questo errore durante la compilazione della mia applicazione con SDL. Ciò è stato causato da SDL che definisce la propria funzione principale in SDL_main.h. Per impedire a SDL di definire la funzione principale, è necessario definire una macro SDL_MAIN_HANDLED prima di includere l'intestazione SDL.h.
Prova a salvare il tuo file .c prima di crearlo. Credo che il tuo computer stia facendo riferimento a un percorso a un file senza informazioni al suo interno.
- Ha avuto un problema simile durante la creazione di progetti C.
Verifica che tutti i file siano inclusi nel tuo progetto:
Ho visualizzato lo stesso errore dopo aver aggiornato cLion. Dopo ore di armeggiare, ho notato che uno dei miei file non era incluso nel target del progetto. Dopo averlo aggiunto di nuovo al progetto attivo, ho smesso di ottenere il riferimento indefinito a winmain16 e il codice è stato compilato.
Modifica: vale anche la pena controllare le impostazioni di build all'interno del tuo IDE.
(Non sono sicuro che questo errore sia correlato al recente aggiornamento dell'IDE - potrebbe essere causale o semplicemente correlativo. Sentiti libero di commentare con qualsiasi intuizione su quel fattore!)
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
. C'è un modo per farloEclipse CDT
visto che non sto usando la riga di comando. Grazie