Quando tento construir um programa usando Eclipse CDT
, obtenho o seguinte:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): referência indefinida para `WinMain @ 16
Por que é que? E como posso resolver esse problema?
Quando tento construir um programa usando Eclipse CDT
, obtenho o seguinte:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): referência indefinida para `WinMain @ 16
Por que é que? E como posso resolver esse problema?
Respostas:
Considere o seguinte programa de nível de API do Windows:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Agora vamos construí-lo usando o conjunto de ferramentas GNU (ou seja, g ++), sem opções especiais. Aqui gnuc
está apenas um arquivo em lote que utilizo para isso. Ele apenas fornece opções para tornar o g ++ mais padrão:
C: \ test> gnuc x.cpp C: \ test> objdump -x a.exe | findstr / i "^ subsistema" Subsistema 00000003 (Windows CUI) C: \ test> _
Isso significa que o vinculador, por padrão, produziu um executável do subsistema do console . O valor do subsistema no cabeçalho do arquivo informa ao Windows quais serviços o programa requer. Neste caso, com o sistema de console, o programa requer uma janela de console.
Isso também faz com que o interpretador de comandos aguarde a conclusão do programa.
Agora vamos construí-lo com o subsistema GUI , o que significa apenas que o programa não requer uma janela de console:
C: \ test> gnuc x.cpp -mwindows C: \ test> objdump -x a.exe | findstr / i "^ subsistema" Subsistema 00000002 (Windows GUI) C: \ test> _
Espero que esteja tudo bem até agora, embora a -mwindows
bandeira esteja apenas semi-documentada.
Construir sem esse sinalizador semidocumentado, seria necessário informar mais especificamente ao vinculador qual valor de subsistema se deseja, e algumas bibliotecas de importação de API do Windows, em geral, terão que ser especificadas explicitamente:
C: \ test> gnuc x.cpp -Wl, -subsystem, windows C: \ test> objdump -x a.exe | findstr / i "^ subsistema" Subsistema 00000002 (Windows GUI) C: \ test> _
Isso funcionou bem, com o conjunto de ferramentas GNU.
Mas e quanto ao conjunto de ferramentas da Microsoft, ou seja, Visual C ++?
Bem, construir como um executável de subsistema de console funciona bem:
C: \ test> msvc x.cpp user32.lib x.cpp C: \ test> dumpbin / headers x.exe | find / i "subsistema" | encontre / i "Windows" 3 subsistema (Windows CUI) C: \ test> _
No entanto, com a construção do conjunto de ferramentas da Microsoft como um subsistema GUI não funciona por padrão:
C: \ test> msvc x.cpp user32.lib / link / subsistema: windows x.cpp LIBCMT.lib (wincrt0.obj): erro LNK2019: símbolo externo não resolvido _WinMain @ 16 referenciado na função ___tmainCRTStartu p x.exe: erro fatal LNK1120: 1 externos não resolvidos C: \ test> _
Tecnicamente, isso ocorre porque o vinculador da Microsoft não é padrão por padrão para o subsistema GUI . Por padrão, quando o subsistema é GUI, o vinculador da Microsoft usa um ponto de entrada da biblioteca de tempo de execução , a função onde a execução do código de máquina começa, chamada winMainCRTStartup
, que chama o não padrão da Microsoft em WinMain
vez do padrão main
.
Não é grande coisa consertar isso.
Tudo o que você precisa fazer é informar ao vinculador da Microsoft qual ponto de entrada usar, ou seja mainCRTStartup
, qual chama padrão main
:
C: \ test> msvc x.cpp user32.lib / link / subsistema: windows / entry: mainCRTStartup x.cpp C: \ test> dumpbin / headers x.exe | find / i "subsistema" | encontre / i "Windows" 2 subsistema (Windows GUI) C: \ test> _
Sem problemas, mas muito tedioso. E tão misterioso e oculto que a maioria dos programadores do Windows, que em sua maioria usam apenas as ferramentas não padronizadas da Microsoft por padrão, nem mesmo sabem sobre isso, e pensam erroneamente que um programa de subsistema da GUI do Windows “deve” ter não padrão em WinMain
vez de padrão main
. De passagem, com C ++ 0x a Microsoft terá um problema com isso, já que o compilador deve anunciar se é independente ou hospedado (quando hospedado, deve suportar o padrão main
).
De qualquer forma, essa é a razão pela qual g ++ pode reclamar da WinMain
falta: é uma função de inicialização não padrão boba que as ferramentas da Microsoft requerem por padrão para programas de subsistema GUI.
Mas, como você pode ver acima, o g ++ não tem problemas com o padrão, main
mesmo para um programa de subsistema de GUI.
Então qual poderia ser o problema?
Bem, provavelmente está faltando um main
. E provavelmente você também não tem (adequado) WinMain
! E então o g ++, depois de ter pesquisado main
(não existe) e o não padrão da Microsoft WinMain
(não existe), informa que o último está faltando.
Testando com uma fonte vazia:
C: \ test> digite nul> y.cpp C: \ test> gnuc y.cpp -mwindows c: / arquivos de programa / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. text + 0xd2 ): referência indefinida ce para `WinMain @ 16 ' collect2: ld retornou 1 status de saída C: \ test> _
main
ou a WinMain
, ou certifique-se de que o arquivo relevante esteja incluído no projeto. Saúde,
main
ou winmain
? Obrigado
Para resumir a postagem acima de Cheers e hth. - Alf, certifique-se de ter main()
ou WinMain()
definido e g ++ deve fazer a coisa certa.
Meu problema é que main()
foi definido dentro de um namespace por acidente.
Eu estava encontrando esse erro ao compilar meu aplicativo com SDL. Isso foi causado por SDL definir sua própria função principal em SDL_main.h. Para evitar que SDL defina a função principal, uma macro SDL_MAIN_HANDLED deve ser definida antes que o cabeçalho SDL.h seja incluído.
Tente salvar seu arquivo .c antes de criar. Acredito que seu computador esteja fazendo referência a um caminho para um arquivo sem nenhuma informação dentro dele.
--Teve um problema semelhante ao construir projetos C
Verifique se todos os arquivos estão incluídos em seu projeto:
Eu tive esse mesmo erro após atualizar o cLion. Após horas de ajustes, percebi que um dos meus arquivos não estava incluído no destino do projeto. Depois de adicioná-lo de volta ao projeto ativo, parei de obter a referência indefinida para winmain16 e o código foi compilado.
Editar: também vale a pena verificar as configurações de construção em seu IDE.
(Não tenho certeza se esse erro está relacionado à atualização recente do IDE - pode ser causal ou simplesmente correlativo. Sinta-se à vontade para comentar com qualquer ideia sobre esse fator!)
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
. Existe uma maneira de fazer issoEclipse CDT
porque não estou usando a linha de comando. Obrigado