Em C, principal não precisa ser uma função?
Pergunta
Esse código compila, mas não surpreende, falha ao vincular (não é o principal encontrado):
Listagem 1:
void main();
Erro de link: mingw lib libmingw32.a (main.o): main.c :(. Texto+0x106) Referência indefinida a _winmain@16 '
Mas, o código abaixo compila e links bem, com um aviso:
Listagem 2:
void (*main)();
Aviso: 'Main' geralmente é uma função
Perguntas:
Na Listagem 1, o vinculador deveria ter reclamado por falta de "Main". Por que está procurando _winmain@16?
O executável gerado na Listagem 2 simplesmente trava. Qual é a razão?
Obrigado pelo seu tempo.
Solução
Caso 1. é específico do Windows - o compilador provavelmente gera _WinMain
símbolo quando main
está adequadamente definido.
Caso 2. - Você tem um ponteiro, mas como variável estática é inicializado para zero, assim o acidente.
Outras dicas
Verdadeiro, main
não precisa ser uma função. Isso foi explorado em alguns programas ofuscados que contêm código de programa binário em uma matriz chamada main
.
O tipo de retorno de main () deve ser int
(não void
). Se o vinculador estiver procurando WinMain
, pensa que você tem um aplicativo da GUI.
Na maioria dos sistemas de compilação C, não há informações de tipo associadas a símbolos vinculados. Você pode declarar principal como por exemplo:
char main[10];
E o ligante ficaria perfeitamente feliz. Como você observou, o programa provavelmente falharia, você mesmo você inicialmente inicializou o conteúdo da matriz.
Seu primeiro exemplo não define o principal, apenas o declara, daí o erro do vinculador.
O segundo exemplo define principal, mas incorretamente.
Nas plataformas do Windows, a unidade principal do programa é o WinMain se você não configurar o programa como um aplicativo de console. O "@16" significa que está esperando 16 bytes de parâmetros. Portanto, o vinculador ficaria muito feliz com você, desde que você lhe desse uma função chamada Winmain com 16 bytes de parâmetros.
Se você desejado Um aplicativo de console, esta é a sua indicação de que você estragou algo.
Você declarou um ponteiro para função chamado Main, e o vinculador avisou que isso não funcionaria.
A mensagem _Winmain tem a ver com a forma como os programas do Windows funcionam. Abaixo do nível do tempo de execução do C, um executável do Windows tem um Winmain.
Tente redefinindo -o como int main(int argc, char *argv[])
O que você tem é um erro de vinculador. O vinculador espera encontrar uma função com essa "assinatura" - não anulada sem parâmetros
Ver http://publications.gbdirect.co.uk/c_book/chapter10/argudes_to_main.html etc.
Na Listagem 1, você está dizendo "há um main () definido em outras partes do meu código-eu prometo!". É por isso que ele compila. Mas você está deitado lá, e é por isso que o link falha. O motivo pelo qual você obtém o erro WinMain16 ausente é porque as bibliotecas padrão (para o Microsoft Compiler) contêm uma definição para Main (), que chama WinMain (). Em um programa Win32, você definiria o WinMain () e o vinculador usaria a versão da biblioteca de Main () para chamar Winmain ().
Na Listagem 2, você tem um símbolo chamado Main definido, para que o compilador e o vinculador sejam felizes, mas o código de inicialização tentará chamar a função que está no local de "Main", e descobre que realmente não há uma função lá, e batida.
1.) Uma função dependente (compilador/plataforma) é chamada antes que o código no principal seja executado e, portanto, seu comportamento (_init
no caso de Linux/Glibc).
2) A falha do código no segundo caso é justificada, pois o sistema não consegue acessar o conteúdo do símbolo main
como uma função que realmente é um ponteiro de função, apontando para o local arbitrário.