Compilar y ejecutar programa sin main () en C
Estoy tratando de compilar y ejecutar el siguiente programa sin la función main()
en C
. He compilado mi programa usando el siguiente comando.
gcc -nostartfiles nomain.c
Y el compilador da una advertencia
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400340
Ok, No hay problema. luego, he ejecutado el archivo ejecutable (a. out), ambas sentencias printf
se imprimen correctamente, y luego obtengo error de segmentación.
Entonces, mi pregunta es, ¿Por qué falla de segmentación después de ejecutar con éxito las instrucciones print?
Mi código:
#include <stdio.h>
void nomain()
{
printf("Hello World...\n");
printf("Successfully run without main...\n");
}
Salida:
Hello World...
Successfully run without main...
Segmentation fault (core dumped)
Nota:
Aquí, -nostartfiles
gcc flag evita que el compilador utilice archivos de inicio estándar al vincular
2 answers
Echemos un vistazo a la asamblea generada de su programa:
.LC0:
.string "Hello World..."
.LC1:
.string "Successfully run without main..."
nomain:
push rbp
mov rbp, rsp
mov edi, OFFSET FLAT:.LC0
call puts
mov edi, OFFSET FLAT:.LC1
call puts
nop
pop rbp
ret
Note la declaración ret
. El punto de entrada de su programa se determina que es nomain
, todo está bien con eso. Pero una vez que la función regresa, intenta saltar a una dirección en la pila de llamadas... eso no está poblado. Eso es un acceso ilegal y sigue un fallo de segmentación.
Una solución rápida sería llamar a exit()
al final de su programa (y suponiendo que C11 también podríamos marcar la función como _Noreturn
):
#include <stdio.h>
#include <stdlib.h>
_Noreturn void nomain(void)
{
printf("Hello World...\n");
printf("Successfully run without main...\n");
exit(0);
}
De hecho, ahora su función se comporta más o menos como una función regular main
, ya que después de regresar de main
, la función exit
se llama con el valor de retorno de main
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-20 18:25:48
En C, cuando se llaman funciones/subrutinas, la pila se rellena como (en el orden):
- Los argumentos,
- Dirección del remitente,
- Variables locales, > > parte superior de la pila
Main() siendo el punto de inicio, ELF estructura el programa de tal manera que cualquier instrucción que venga primero sería empujada primero, en este caso printfs son.
Ahora, el programa es una especie de truncado sin dirección de retorno O __end__
y de hecho asume que lo que hay en la pila en esa ubicación (__end__
) es la dirección de retorno, pero desafortunadamente no es así y por lo tanto se bloquea.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-19 17:54:16