128 votes

Référence indéfinie à `WinMain@16'.

Lorsque j'essaie de construire un programme en utilisant Eclipse CDT J'obtiens ce qui suit :

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

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

2 votes

Essayez de sauvegarder votre fichier et de le ré-exécuter dans mon cas, cela a fonctionné.

201voto

Cette erreur se produit lorsque l'éditeur de liens ne peut trouver WinMain donc elle est probablement manquante. Dans votre cas, il vous manque probablement main aussi.

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 );
}

Maintenant, construisons-le en utilisant la chaîne d'outils GNU (i.e. g++), sans options spéciales. Voici gnuc est juste un fichier batch que j'utilise pour ça. Il fournit seulement des options pour rendre g++ plus standard :

C:\\test> gnuc x.cpp

C:\\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem               00000003        (Windows CUI)

C:\\test> \_

Cela signifie que l'éditeur de liens a produit par défaut un fichier sous-système de la console exécutable. Le site 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 console, que le programme nécessite une fenêtre console.

L'interpréteur de commandes attend alors que le programme se termine.

Maintenant, nous allons le construire avec Sous-système GUI ce qui signifie simplement que le programme n'a pas besoin d'une fenêtre de console :

C:\\test> gnuc x.cpp -mwindows

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

C:\\test> \_

J'espère que c'est bon jusqu'à présent, bien que la -mwindows est juste semi-documenté.

En construisant sans ce drapeau semi-documenté, il faudrait indiquer plus spécifiquement à l'éditeur de liens quelle valeur de sous-système on souhaite, et certaines bibliothèques d'importation de l'API Windows devront alors être spécifiées explicitement :

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

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

C:\\test> \_

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

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

Eh bien, la construction en tant qu'exécutable du sous-système de la console fonctionne bien :

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> \_

Cependant, avec la chaîne d'outils de Microsoft, la construction d'un sous-système GUI ne fonctionne pas par défaut :

C:\\test> msvc x.cpp user32.lib /link /subsystem:windows
x.cpp
LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol \_WinMain@16 referenced in function \_\_\_tmainCRTStartu
p
x.exe : fatal error LNK1120: 1 unresolved externals

C:\\test> \_

Techniquement, c'est parce que l'éditeur de liens de Microsoft est non standard par défaut pour le sous-système GUI . Par défaut, lorsque le sous-système est une interface graphique, l'éditeur de liens de Microsoft utilise une bibliothèque d'exécution. point d'entrée la fonction où l'exécution du code machine commence, appelée winMainCRTStartup qui appelle le système non standard de Microsoft WinMain au lieu de la norme main .

Ce n'est pas un problème de réparer ça, cependant.

Tout ce que vous avez à faire est d'indiquer à l'éditeur de liens de Microsoft le point d'entrée à utiliser, à savoir mainCRTStartup qui appelle la norme 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> \_

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

Quoi qu'il en soit, c'est la raison pour laquelle g++ puede se plaindre de WinMain manquant : il s'agit d'une fonction de démarrage stupide et non standard que les outils de Microsoft exigent par défaut pour les programmes du sous-système GUI.

Mais comme vous pouvez le voir ci-dessus, g++ n'a aucun problème avec le standard main même pour un programme de sous-système GUI.

Alors quel pourrait être le problème ?

Eh bien, vous êtes probablement manquant a main . Et vous n'avez probablement pas (correctement) WinMain soit ! Et puis g++, après avoir cherché main (qui n'existe pas), et pour le système non standard de Microsoft WinMain (pas de tel), signale que ce dernier est manquant.

Test avec une source vide :

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 returned 1 exit status

C:\\test> \_

3 votes

Alf P. Steinbach. Merci beaucoup pour votre belle réponse. En ce qui concerne All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main . Y a-t-il un moyen de le faire Eclipse CDT car je n'utilise pas la ligne de commande. Merci

1 votes

@user588855 : puisque vous utilisez g++, cela ne s'applique (probablement) pas à vous. Seule la partie à la fin s'applique (probablement). C'est-à-dire, définissez un main ou un WinMain ou assurez-vous que le fichier correspondant est inclus dans le projet. A la vôtre,

0 votes

@Alf P. Steinbach. Que voulez-vous dire par définir main o winmain ? Merci

83voto

Tim Ludwinski Points 457

Pour résumer le post ci-dessus par Cheers et hth. - Alf, Assurez-vous que vous avez main() o WinMain() défini et g++ devrait faire la bonne chose.

Mon problème était que main() a été défini à l'intérieur d'un espace de nom par accident.

0 votes

Je viens de réaliser quelque chose d'important à propos de tout ça. Dans mon cas, il ne trouvait pas main() car je n'avais pas déclaré d'arguments (argc, argv). Une fois ajouté, il a trouvé main. Aussi, la nature de la façon dont cela fonctionne signifie que mingw essaie d'aider en fournissant son propre main qui à son tour appelle WinMain. Les programmes GUI n'auraient que WinMain et le stub main de mingw est utilisé pour y arriver. Si vous avez un main, alors il l'utilise à la place.

0 votes

Extern "C" int main(void) a réglé le problème pour moi

37voto

X-Frox Points 41

Je rencontrais cette erreur lors de la compilation de mon application avec SDL. La cause en était que SDL définissait sa propre fonction principale dans SDL_main.h. Pour empêcher SDL de définir la fonction principale, il faut définir la macro SDL_MAIN_HANDLED avant d'inclure l'en-tête SDL.h.

0 votes

Merci beaucoup ! Cette commande fonctionne : 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

14voto

JabbaJava Points 31

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 qui ne contient aucune information.

4voto

user1883961 Points 36

Ma situation était que je n'avais pas de fonction principale.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X