Aprendí de mi colega que uno puede escribir y ejecutar un programa en C sin escribir una main()
función. Se puede hacer así:
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;
}
Compílalo con este comando:
gcc -o my_main my_main.c –nostartfiles
Ejecútalo con este comando:
./my_main
¿Cuándo se necesitaría hacer este tipo de cosas? ¿Hay algún escenario del mundo real en el que esto sea útil?
_start()
y otros aspectos externosmain()
._start
ni sobre ningún punto de entrada que no seamain
(excepto que el nombre del punto de entrada está definido por la implementación para implementaciones independientes (incrustadas)).Respuestas:
El símbolo
_start
es el punto de entrada de su programa. Es decir, la dirección de ese símbolo es la dirección saltada al inicio del programa. Normalmente, la función con el nombre_start
es suministrada por un archivo llamadocrt0.o
que contiene el código de inicio para el entorno de tiempo de ejecución C. Configura algunas cosas, llena la matriz de argumentosargv
, cuenta cuántos argumentos hay y luego llamamain
. Luego demain
retornos,exit
se llama.Si un programa no desea utilizar el entorno de tiempo de ejecución C, debe proporcionar su propio código
_start
. Por ejemplo, la implementación de referencia del lenguaje de programación Go lo hace porque necesitan un modelo de subprocesamiento no estándar que requiere algo de magia con la pila. También es útil proporcionar el suyo propio_start
cuando desea escribir programas realmente pequeños o programas que hacen cosas poco convencionales.fuente
_start
proviene del archivo objetocrt0.o
._start
; de hecho, no especifica lo que sucede antes de quemain
se llame, solo especifica qué condiciones se deben cumplir cuandomain
se llama. Es más una convención para el punto de entrada_start
que se remonta a los viejos tiempos.Si bien
main
es el punto de entrada para su programa desde la perspectiva de los programadores,_start
es el punto de entrada habitual desde la perspectiva del sistema operativo (la primera instrucción que se ejecuta después de que su programa se inició desde el sistema operativo)En un programa típico de C y especialmente de C ++, se ha realizado mucho trabajo antes de que la ejecución entre en main.
Especialmente cosas como la inicialización de variables globales.Aquí se puede encontrar una buena explicación de todo lo que está pasando entre_start()
ymain()
y también después de principal ha salido de nuevo (ver comentario más abajo).El código necesario para eso generalmente lo proporcionan los escritores del compilador en un archivo de inicio, pero con el indicador
–nostartfiles
esencialmente le dice al compilador: "No te molestes en darme el archivo de inicio estándar, dame un control total sobre lo que está sucediendo desde el comienzo".Esto a veces es necesario y a menudo se usa en sistemas integrados. Por ejemplo, si no tiene un sistema operativo y tiene que habilitar manualmente ciertas partes de su sistema de memoria (por ejemplo, cachés) antes de la inicialización de sus objetos globales.
fuente
_start()
(o en realidad otra función llamada por él) y en muchos Programas Bare-Metal, copia explícitamente todos los datos globales de flash a RAM primero, lo que también ocurre en_start()
, pero esta pregunta no era sobre c ++ ni sobre código de metal desnudo._start
, la biblioteca C no se inicializará a menos que tome medidas especiales para hacerlo usted mismo; puede ser inseguro usar cualquier función segura de señal no asíncrona de dicho programa. (No hay garantía oficial de que ninguna función de biblioteca funcionará, pero las funciones seguras de señal asíncrona no pueden referirse a ningún dato global, por lo que tendrían que hacer todo lo posible por un mal funcionamiento).malloc
no se inicializan las estructuras de datos internas para .errno
(por ejemplo,read
ywrite
son async señal-seguro y puede establecererrno
) y que posiblemente podría ser un problema dependiendo exactamente cuando el per-hiloerrno
se asigna ubicación .Aquí hay una buena descripción general de lo que sucede antes durante el inicio del programa
main
. En particular, muestra que__start
es el punto de entrada real a su programa desde el punto de vista del sistema operativo.Es la primera dirección desde la cual el puntero de instrucción comenzará a contar en su programa.
El código allí invoca algunas rutinas de biblioteca de tiempo de ejecución de C solo para hacer algunas tareas de limpieza, luego llamar a su
main
, y luego bajar las cosas y llamarexit
con cualquier código de salidamain
devuelto.Una imagen vale mas que mil palabras:
PD: esta respuesta se trasplanta de otra pregunta que SO ha cerrado útilmente como duplicado de esta.
fuente
Cuando desee su propio código de inicio para su programa.
main
No es la primera entrada para un programa en C,_start
es la primera entrada detrás de la cortina.Ejemplo en Linux:
Si quiere decir, implemente el nuestro
_start
:Sí, en la mayoría del software comercial integrado con el que he trabajado, necesitamos implementar el nuestro con
_start
respecto a nuestros requisitos específicos de memoria y rendimiento.Si quiere decir, suelte la
main
función y cámbiela a otra cosa:No, no veo ningún beneficio haciendo eso.
fuente