¿Hay alguna forma de que un progtwig C / C ++ se cuelgue antes de main ()?

¿Hay alguna forma en que un progtwig puede fallar antes de main ()?

Con gcc, puede etiquetar una función con el atributo constructor (que hace que la función se ejecute antes que main ). En la siguiente función, se premain a premain antes de main :

 #include  void premain() __attribute__ ((constructor)); void premain() { fputs("premain\n", stdout); } int main() { fputs("main\n", stdout); return 0; } 

Por lo tanto, si hay un error de locking en premain , se bloqueará antes que el main .

Sí, al menos bajo Windows. Si el progtwig utiliza archivos DLL, pueden cargarse antes de que comience main() . Las funciones DllMain de esas DLL se ejecutarán antes de main() . Si encuentran un error, podrían hacer que todo el proceso se detenga o se bloquee.

Si tiene un progtwig en C ++, puede inicializar variables y objetos a través de funciones y constructores antes de ingresar a main. Un error en cualquiera de estos podría causar la falla de un progtwig.

ciertamente en c ++; objetos estáticos con constructores serán llamados antes que principales – pueden morir

no estoy seguro acerca de c

aquí está la muestra

 class X { public: X() { char *x = 0; *x = 1; } }; X x; int main() { return 0; } 

esto se bloqueará antes principal

La respuesta simple es: .

Más específicamente, podemos diferenciar entre dos causas para esto. Los llamaré dependientes de la implementación e independientes de la implementación .

El único caso que no depende en absoluto de su entorno es el de los objetos estáticos en C ++, que se mencionó aquí. El siguiente código muere antes de main() :

 #include  class Useless { public: Useless() { throw "You can't construct me!"; } }; static Useless object; int main() { std::cout << "This will never be printed" << std::endl; return 0; } 

Más interesantes son las causas dependientes de la plataforma . Algunos fueron mencionados aquí. Uno que se mencionó aquí un par de veces fue el uso de bibliotecas vinculadas dinámicamente (DLL en Windows, SOs en Linux, etc.) - si el cargador de su SO las carga antes de main() , pueden hacer que su aplicación muera antes de main()

Una versión más general de esta causa es hablar de todas las cosas que hace el punto de entrada de su binario antes de llamar a su punto de entrada ( main() ). Usualmente cuando construyes tu binario hay un bloque de código bastante serio que se invoca cuando el cargador de tu sistema operativo comienza a ejecutar tu archivo binario, y cuando lo hace llama a tu main() . Una cosa común de este código es inicializar la biblioteca estándar de C / C ++. Este código puede fallar por cualquier cantidad de razones (escasez de cualquier tipo de recurso del sistema que intente asignar para uno).

Una manera interesante de que un código binario ejecute código antes de que main() en windows use callbacks de TLS (google le dirá más sobre ellos). Esta técnica generalmente se encuentra en el malware como un truco básico contra la depuración (este truco utilizado para engañar a ollydbg en aquel entonces, no sé si todavía lo hace).

El punto es que su pregunta es en realidad equivalente a "¿hay alguna forma de que cargar un código binario haga que el código de usuario se ejecute antes que el código en main() ?", Y la respuesta es el infierno, ¡sí!

Cualquier progtwig que se base en objetos compartidos (DLL) cargados antes de main puede fallar antes que main.

Bajo el código de Linux en la biblioteca del enlazador dynamic (ld – *. So) se ejecuta para suministrar dependencias de biblioteca mucho antes que main. Si las bibliotecas necesarias no se pueden ubicar, tener permisos que no le permiten acceder a ellas, no son archivos normales, o no tienen algún símbolo que el vinculador dynamic que unía su progtwig pensó que debería tener cuando enlazó su progtwig, entonces esto puede causar un error.

Además, cada biblioteca puede ejecutar algún código cuando está vinculado. Esto se debe principalmente a que la biblioteca puede necesitar vincular más bibliotecas o puede necesitar ejecutar algunos constructores (incluso en un progtwig C, las bibliotecas podrían tener algún C ++ u otra cosa que use constroctors). Además, los progtwigs estándar C ya han creado stdio FILE stdin, stdout y stderr. En muchos sistemas, estos también se pueden cerrar. Esto implica que también son libres () ed, lo que implica que ellos (y sus almacenamientos intermedios) fueron malloc () ed, que pueden fallar. También sugiere que pueden haber hecho otras cosas en los descriptores de archivos que representan esas estructuras de ARCHIVO, que podrían fallar.

Otras cosas que podrían suceder podrían ser si el sistema operativo se equivoca al configurar las variables ambientales y / o los argumentos de la línea de comando que se pasaron al progtwig. Código antes de main es probable que haya tenido algo con estos datos antes de llamar a main.

Muchas cosas pasan antes de main. Cualquiera de ellos puede fracasar notablemente de una manera fatal.

No estoy seguro, pero si tienes una variable global como esta:

 static SomeClass object; int main(){ return 0; } 

El constructor ‘SomeClass’ podría colapsar el progtwig antes de que se ejecute el principal.

Hay muchas posibilidades

Primero, necesitamos entender qué sucede realmente antes de que se ejecute main:

  • Carga de bibliotecas dinámicas
  • Inicialización de globales
  • Uno algunos comstackdores, algunas funciones se pueden ejecutar explícitamente

Ahora, todo esto puede causar un locking de varias maneras:

  • el comportamiento indefinido habitual (desreferenciando puntero nulo, accediendo a la memoria no debería …)
  • una excepción lanzada> ya que no hay catch , se llama a terminate y el progtwig termina

Es realmente molesto por supuesto y posiblemente difícil de depurar, y es por eso que debes abstenerte de ejecutar código antes de main tanto como sea posible, y prefieres la inicialización lenta si puedes, o la inicialización explícita en main .

Por supuesto, cuando falla una DLL y no puedes modificarla, te espera un mundo de dolor.

Clase de: http://blog.ksplice.com/2010/03/libc-free-world/

Si comstack sin biblioteca estándar, haga lo siguiente: gcc -nostdlib -o hello hello.c

no sabrá cómo ejecutar main () y se bloqueará.

Los objetos globales y estáticos en un progtwig C ++ tendrán sus constructores llamados antes de que se ejecute la primera instrucción en main (), por lo que un error en uno de los constructores puede causar un locking.

Esto no puede suceder en los progtwigs C, sin embargo.

Depende de lo que quiera decir con “antes principal”, pero si quiere decir “antes de que se ejecute realmente alguno de sus códigos en main”, entonces puedo pensar en un ejemplo: si declara una matriz grande como una variable local en main, y la el tamaño de esta matriz excede el espacio de la stack disponible, entonces es posible que obtenga un stack overflow en la entrada principal, antes de que se ejecute la primera línea de código.

Un ejemplo algo artificial sería:

 int a = 1; int b = 0; int c = a / b; int main() { return 0; } 

Es poco probable que alguna vez hagas algo como esto, pero si estás haciendo un montón de macro magia, es completamente posible.

 class Crash { public: Crash( int* p ) { *p = 0; } }; static Crash static_crash( 0 ); void main() { } 

Claro, si hay un error en el sistema operativo o en el código de tiempo de ejecución. C ++ es particularmente notorio por este comportamiento, pero aún puede ocurrir en C.

No has dicho qué plataforma / libc. En el mundo integrado, con frecuencia hay muchas cosas que se ejecutan antes de main() , principalmente relacionadas con la configuración de la plataforma, que pueden salir mal. (O, de hecho, si está utilizando un script de enlazador funky en un sistema operativo normal, todas las apuestas están desactivadas, pero supongo que es bastante raro).

algunas bibliotecas de abstracción de plataforma sobrescriben (yo personalmente solo conozco bibliotecas de C ++ como Qt o ACE, que hacen esto, pero tal vez algunas bibliotecas de C hacen algo así también) “principal”, para que especifiquen una principal específica de plataforma como un int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ); y configure algunas cosas de la biblioteca, convierta los args de la línea de comando al int argc, char* argv[] y luego llame al int main(int argc, char* argv[]) normal int main(int argc, char* argv[])

Por supuesto, estas bibliotecas podrían provocar un locking cuando no implementan esto correctamente (tal vez causa errores de línea de comando mal formados).

Y para las personas que no saben sobre esto, esto puede parecer una caída antes de main

Me enfrenté al mismo problema. La causa raíz que se encontró fue … Demasiadas variables locales (matrices enormes) se inicializaron en el proceso principal, llevando el tamaño de las variables locales a más de 1,5 mb.
Esto da como resultado un gran salto ya que el puntero de la stack es bastante grande y el sistema operativo detecta este salto como no válido y bloquea el progtwig, ya que podría ser malicioso.

Para depurar esto
1. Arranca GDB
2. Agregue un punto de interrupción en main
3. desmontar principal
4. Verifique por sub $ 0xGGGGGGG,% esp
Si este valor de GGGGGG es demasiado alto, verá el mismo problema que yo.

Por lo tanto, verifique el tamaño total de todas las variables locales en la principal.