web-dev-qa-db-fra.com

référence non définie à `WinMain @ 16 '

Lorsque j'essaie de créer un programme en utilisant Eclipse CDT, j'obtiens les informations suivantes:

/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): référence non définie à `WinMain @ 16

Pourquoi donc? Et comment puis-je résoudre ce problème?

101
Simplicity

Considérez le programme de niveau API Windows suivant:

#define NOMINMAX
#include <windows.h>

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

Construisons-le maintenant en utilisant GNU toolchain (c'est-à-dire g ++), sans options spéciales. Ici gnuc est juste un fichier de commandes que j'utilise pour cela. Il ne fournit que des options pour rendre g ++ plus standard:

 C:\test> gnuc x.cpp 
 
 C:\test> objdump -x a.exe | findstr/i "^ sous-système" 
 Sous-système 00000003 (Windows CUI) 
 
 C:\test> _ 

Cela signifie que l'éditeur de liens a créé par défaut un exécutable de la console . La valeur du sous-système dans l'en-tête du fichier indique à Windows les services requis par le programme. Dans ce cas, avec le système de console, le programme nécessite une fenêtre de console.

Cela oblige également l'interpréteur de commandes à attendre la fin du programme.

Construisons-le maintenant avec sous-système graphique , ce qui signifie simplement que le programme ne nécessite pas de fenêtre de console:

 C:\test> gnuc x.cpp -mwindows 
 
 C:\test> objdump -x a.exe | findstr/i "^ sous-système" 
 Sous-système 00000002 (interface graphique Windows) 
 
 C:\test> _ 

J'espère que ça ira jusqu'à présent, bien que le drapeau -mwindows soit juste semi-documenté.

Pour construire sans cette balise semi-documentée, il faudrait indiquer plus spécifiquement à l'éditeur de liens quelle valeur de sous-système on souhaite, et certaines bibliothèques d'importation API Windows devront ensuite être spécifiées de manière explicite:

 C:\test> gnuc x.cpp -Wl, -sous-système, windows 
 
 C:\test> objdump -x a.exe | findstr/i "^ sous-système" 
 Sous-système 00000002 (interface graphique Windows) 
 
 C:\test> _ 

Cela a bien fonctionné, avec la chaîne d’outils GNU.

Mais qu’en est-il de la chaîne d’outils Microsoft, c’est-à-dire Visual C++?

Bien, compiler un exécutable de sous-système de console fonctionne bien:

 C:\test> msvc x.cpp user32.lib 
 X.cpp 
 
 C:\test> dumpbin/headers x.exe | find/i "sous-système" | find/i "Windows" 
 3 sous-système (Windows CUI) 
 
 C:\test> _ 

Cependant, la construction de la chaîne d’outils de Microsoft en tant que sous-système graphique ne fonctionne pas par défaut:

 C:\test> msvc x.cpp user32.lib/link /subsystem:windows
x.cpp
LIBCMT.lib(wincrt0.obj): erreur LNK2019: externe non résolue symbole _WinMain @ 16 référencé dans la fonction ___ tmainCRTStartu 
 p 
 x.exe: erreur fatale LNK1120: 1 externales non résolues 
 
 C:\test> _ 

Techniquement, cela s’explique par le fait que l’éditeur de liens de Microsoft est non standard par défaut pour le sous-système graphique . Par défaut, lorsque le sous-système est une interface graphique, l'éditeur de liens de Microsoft utilise un point d'entrée de bibliothèque , la fonction de démarrage de l'exécution du code machine, appelée winMainCRTStartup, qui appelle le système non standard de Microsoft WinMain au lieu de la valeur standard main.

Pas de problème pour résoudre ce problème, cependant.

Tout ce que vous avez à faire est de dire à l'éditeur de liens de Microsoft le point d'entrée à utiliser, à savoir mainCRTStartup, qui appelle la norme main:

 C:\test> msvc x.cpp utilisateur32.lib/link/sous-système: fenêtres/entrée: mainCRTStartup 
 X.cpp 
 
 C:\test> dumpbin/headers x.exe | find/i "sous-système" | find/i "Windows" 
 2 sous-système (interface graphique Windows) 
 
 C:\test> _ 

Pas de problème, mais très fastidieux. Et tellement mystérieux et caché que la plupart des programmeurs Windows, qui utilisent principalement des outils non standard par défaut de Microsoft, ne le savent même pas et pensent à tort qu’un programme de sous-système à interface graphique Windows "doit" avoir WinMain non standard au lieu de standard main. En passant, avec C++ 0x, Microsoft aura un problème avec cela, car le compilateur doit ensuite annoncer s'il est autonome ou hébergé (lorsqu'il est hébergé, il doit prendre en charge la norme main).

Quoi qu'il en soit, c'est la raison pour laquelle g ++ peut se plaindre de l'absence de WinMain: il s'agit d'une fonction de démarrage stupide et non standard que les outils de Microsoft requièrent par défaut pour les programmes de sous-système à interface graphique.

Mais comme vous pouvez le voir ci-dessus, g ++ n’a aucun problème avec la norme main même pour un programme de sous-système à interface graphique.

Alors, quel pourrait être le problème?

Eh bien, il vous manque probablement un main. Et vous n’avez probablement pas non plus de (correct) WinMain! Ensuite, g ++, après avoir recherché main (aucun de ces types) et Microsoft non standard WinMain (aucun de ces types), indique que ce dernier est manquant.

Test avec une source vide:

 C:\test> type nul> y.cpp 
 
 C:\test> gnuc y.cpp -mwindows 
 C:/fichiers de programme/mingw/bin /../ lib/gcc/mingw32/4.4.1 /../../../ libmingw32.a (main.o): main.c: (. text. + 0xd2): référent non défini 
 ce à `WinMain @ 16 '
 collect2: ld a renvoyé 1 état de sortie 
 
 C:\test> _ 
171

Pour résumer le post ci-dessus par Cheers et hth. - Alf, assurez-vous que vous avez défini main() ou WinMain() et que g ++ doit agir correctement.

Mon problème était que main() a été défini par accident dans un espace de noms.

62
Tim Ludwinski

Je rencontrais cette erreur lors de la compilation de mon application avec SDL. Cela est dû au fait que SDL a défini sa propre fonction principale dans SDL_main.h. Pour éviter que SDL définisse la fonction principale, une macro SDL_MAIN_HANDLED doit être définie avant que l'en-tête SDL.h ne soit inclus.

25
X-Frox

Essayez de sauvegarder votre fichier .c avant de le construire. Je crois que votre ordinateur fait référence à un chemin d'accès à un fichier sans aucune information à l'intérieur.

--Had problème similaire lors de la construction de projets C

1
JabbaJava