Aprendi com meu colega que se pode escrever e executar um programa C sem escrever uma main()
função. Isso pode ser feito assim:
my_main.c
/* Compile this with gcc -nostartfiles */
#include <stdlib.h>
void _start() {
int ret = my_main();
exit(ret);
}
int my_main() {
puts("This is a program without a main() function!");
return 0;
}
Compile com este comando:
gcc -o my_main my_main.c –nostartfiles
Execute-o com este comando:
./my_main
Quando alguém precisaria fazer esse tipo de coisa? Existe algum cenário do mundo real em que isso seria útil?
_start()
e outras coisas fora demain()
._start
, ou sobre qualquer ponto de entrada que não sejamain
(exceto que o nome do ponto de entrada é definido pela implementação para implementações independentes (incorporadas)).Respostas:
O símbolo
_start
é o ponto de entrada do seu programa. Ou seja, o endereço desse símbolo é o endereço saltado no início do programa. Normalmente, a função com o nome_start
é fornecida por um arquivo chamadocrt0.o
que contém o código de inicialização para o ambiente de tempo de execução C. Ele cria algumas coisas, preenche a matriz de argumentosargv
, conta quantos argumentos existem e depois chamamain
. Apósmain
retornos,exit
é chamado.Se um programa não quiser usar o ambiente de tempo de execução C, precisará fornecer seu próprio código
_start
. Por exemplo, a implementação de referência da linguagem de programação Go faz isso porque eles precisam de um modelo de encadeamento não padrão que exija alguma mágica com a pilha. Também é útil fornecer o seu próprio_start
quando você deseja escrever programas realmente minúsculos ou programas que fazem coisas não convencionais.fonte
_start
vem do arquivo de objetocrt0.o
._start
; de fato, ele não especifica o que acontece antes demain
ser chamado, apenas especifica quais condições devem ser atendidas quandomain
é chamado. É mais uma convenção para o ponto de entrada_start
que remonta aos velhos tempos.Embora
main
seja o ponto de entrada para o seu programa da perspectiva dos programadores,_start
é o ponto de entrada usual da perspectiva do SO (a primeira instrução executada após o início do programa no SO)Em um programa típico em C e especialmente em C ++, muito trabalho foi feito antes da execução entrar no main.
Especialmente coisas como inicialização de variáveis globais.Aqui você pode encontrar uma boa explicação de tudo o que está acontecendo entre_start()
emain()
depois da saída do main novamente (veja o comentário abaixo).O código necessário para isso geralmente é fornecido pelos gravadores do compilador em um arquivo de inicialização, mas com o sinalizador
–nostartfiles
você basicamente diz ao compilador: "Não se incomode em me fornecer o arquivo de inicialização padrão, me dê controle total sobre o que está acontecendo diretamente no começar".Às vezes, isso é necessário e frequentemente usado em sistemas embarcados. Por exemplo, se você não possui um sistema operacional e precisa habilitar manualmente certas partes do seu sistema de memória (por exemplo, caches) antes da inicialização de seus objetos globais.
fonte
_start()
(ou na verdade outra função chamada por ele) e em muitos programas bare-metal, você copia explicitamente todos os dados globais do flash para a RAM primeiro, o que também acontece_start()
, mas essa pergunta não era sobre c ++ nem código bare-metal._start
, a biblioteca C não será inicializada, a menos que você tome medidas especiais para fazer isso sozinho - pode ser perigoso usar qualquer função segura de sinal não-assíncrono desse programa. (Não há garantia oficial de que qualquer função da biblioteca funcione, mas as funções seguras de sinal assíncrono não podem se referir a nenhum dado global, portanto elas teriam que semalloc
não são inicializadas.errno
(por exemplo,read
ewrite
são async-signal-seguro e pode definirerrno
) e que poderia concebivelmente ser um problema dependendo exatamente quando o por threaderrno
local é alocado .Aqui está uma boa visão geral do que acontece antes da inicialização do programa
main
. Em particular, mostra que esse__start
é o ponto de entrada real do seu programa do ponto de vista do SO.É o primeiro endereço a partir do qual o ponteiro de instruções começará a contar no seu programa.
O código lá chama algumas rotinas da biblioteca de tempo de execução C apenas para realizar algumas tarefas domésticas, depois chamar seu
main
e, em seguida, interromper as coisas e chamarexit
com qualquer código de saídamain
retornado.Uma imagem vale mais que mil palavras:
PS: esta resposta é transplantada de outra pergunta que SO fechou útil como duplicada desta.
fonte
Quando você deseja seu próprio código de inicialização para o seu programa.
main
não é a primeira entrada para um programa C,_start
é a primeira entrada atrás da cortina.Exemplo no Linux:
Se você quer dizer, implemente o nosso
_start
:Sim, na maioria dos softwares comerciais incorporados com os quais trabalhei, precisamos implementar nossos próprios em
_start
relação aos nossos requisitos específicos de memória e desempenho.Se você quer dizer, largue a
main
função e altere-a para outra coisa:Não, não vejo nenhum benefício em fazer isso.
fonte