todas tipos retorno programa por parametros linea lenguaje las funciones funcion ejemplos ejecutar con como comandos c gcc segmentation-fault main gcc-warning

tipos - Compile y ejecute el programa sin main() en C



tipos de funciones en c (2)

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 advertencia

/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400340

Está bien, no hay problema. luego, ejecuté el archivo ejecutable (a.out), ambas declaraciones printf imprimieron con éxito y luego obtuve un error de segmentación .

Entonces, mi pregunta es: ¿Por qué falla la segmentación después de ejecutar correctamente las declaraciones de impresión?

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í, el -nostartfiles gcc evita que el compilador use archivos de inicio estándar al vincular


Echemos un vistazo al assembly generado 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

Tenga en cuenta la declaración ret . Se determina que el punto de entrada de su programa 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 ... que no se completa. Ese es un acceso ilegal y sigue una falla 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 main normal, ya que después de regresar de main , la función de exit se llama con el valor de retorno de main .


En C, cuando se llaman funciones / subrutinas, la pila se llena como (en el orden):

  1. Los argumentos,
  2. Dirección del remitente,
  3. Variables locales, -> parte superior de la pila

siendo main () el punto de inicio, ELF estructura el programa de tal manera que cualquier instrucción que venga primero se empujará primero, en este caso, printfs es.

Ahora, el programa está truncado sin la dirección de retorno O __end__ y de hecho supone que todo lo que hay en la pila en esa ubicación ( __end__ ) es la dirección de retorno, pero desafortunadamente no lo es y por lo tanto se bloquea.