Pregunta

Estoy trabajando para portar una aplicación de Visual C++ a GCC (debería basarse en MingW y Linux).

El código existente utiliza __try { ... } __except(1) { ... } se bloquea en algunos lugares para que casi nada (excepto quizás errores de tipo falta de memoria) haga que el programa salga sin realizar un registro mínimo.

¿Cuáles son las opciones para hacer algo similar con GCC?

Editar:Gracias por el puntero a las opciones /EH en Visual Studio, lo que necesito ahora son algunos ejemplos sobre cómo manejar señales en Linux.He encontrado este mensaje desde 2002.

¿Qué otras señales además SIGFPE y SIGSEVG ¿debo tener cuidado?(Se preocupan principalmente por los que podrían surgir de a mí haciendo algo mal)

Información de recompensa:Quiero que mi aplicación pueda registrar automáticamente tantas condiciones de error como sea posible antes de salir.

¿Qué señales puedo recibir y después de cuáles sería generalmente imposible registrar un mensaje de error?(Sin memoria, ¿qué más?)

¿Cómo puedo manejar excepciones y (lo más importante) señales de forma portátil de que el código al menos funciona igual en Linux y MingW?#ifdef está bien.

La razón por la que no tengo un proceso contenedor que registre el error es que, por razones de rendimiento, guardo la escritura de algunos datos en el disco hasta el último minuto, por lo que si algo sale mal, quiero hacer todos los intentos posibles para escribir los datos antes. saliendo.

¿Fue útil?

Solución

try { xxx } catch(...) { xxx } sería más portátil pero podría no captar tanto.Depende de la configuración y los entornos del compilador.

Al utilizar la configuración predeterminada de VC++, los errores asincrónicos (SEH) no se envían a la infraestructura EH de C++;para detectarlos, debe utilizar controladores SEH (__try/__except) en su lugar.VC++ le permite enrutar errores SEH a través del manejo de errores de C++, lo que permite que un catch(...) capture los errores SEH;esto incluye errores de memoria como desreferencias de puntero nulo. Detalles.

En Linux, sin embargo, muchos de los errores para los que Windows utiliza SEH se indican mediante señales.Estos nunca son capturados por try/catch;para manejarlos necesitas un manejador de señales.

Otros consejos

¿Por qué no utilizar las excepciones estándar de C++ en lugar de la extensión propietaria de MSFT?C++ tiene un concepto de manejo de excepciones.

struct my_exception_type : public logic_error {
    my_exception_type(char const* msg) : logic_error(msg) { }
};

try {
    throw my_exception_type("An error occurred");
} catch (my_exception_type& ex) {
    cerr << ex.what << endl;
}

C++ también tiene una cláusula "general", por lo que si desea registrar excepciones, puede utilizar el siguiente contenedor:

try {
    // …
}
catch (...) {
}

Sin embargo, esto no es muy eficiente en C++ porque crear un contenedor tan general significa que el código de manejo debe insertarse en cada marco de pila posterior por parte del compilador (a diferencia de los sistemas administrados como .NET, donde el manejo de excepciones no tiene costo adicional siempre que no se genere ninguna excepción).

Para la portabilidad, una cosa que puede intentar es usar bloques try-catch para la mayoría de las excepciones básicas y luego configurar un controlador de terminación (set_terminate_handler) para tener un gancho mínimo disponible para condiciones de salida catastróficas.También puedes intentar agregar algo como un controlador atexit o on_exit.Por supuesto, su entorno de ejecución puede ser extraño o corrupto cuando ingresa a estas funciones, así que tenga cuidado con lo mucho que presupone un entorno sensato.

Finalmente, cuando use pares try-catch regulares, puede considerar usar bloques try de función en lugar de abrir un bloque try en el cuerpo de una función:

int foo(int x) try {
  // body of foo
} catch (...) {
   // be careful what's done here!
}

son una parte relativamente desconocida de C++ y, en algunos casos, pueden ofrecer recuperación incluso en caso de corrupción parcial (de pequeña escala) de la pila.

Finalmente, sí, probablemente querrás investigar qué señales puedes manejar de forma continua por tu cuenta o cuáles podrías abortar, y si quieres implementar menos mecanismos de manejo, podrías considerar llamar a la versión sin lanzamiento del nuevo operador. y compilar para no generar excepciones de punto flotante si es necesario (siempre puede verificar isnan(.), isfinite(.), en los resultados de FP para protegerse).

En esa última nota, tenga cuidado:He notado que las funciones de clasificación de resultados de punto flotante pueden estar en diferentes encabezados en Linux y Windows...por lo que es posible que tengas que condicionar esas inclusiones.

Si te sientes travieso, escríbelo todo usando setjmp y longjmp (eso es una broma...).

Detectar excepciones de C++ con catch(...) Ya te sitúa en una zona desconocida.

Tratando de detectar errores no detectados por catch(...) te coloca directamente dentro de un comportamiento indefinido.No se garantiza que ningún código C++ funcione.Su código de registro mínimo puede hacer que se lance el misil.

Mi recomendación es que ni siquiera lo intentes. catch(...).Detecte únicamente las excepciones que pueda registrar de manera significativa y segura y deje que el sistema operativo se encargue del resto, si corresponde.

La depuración postmortem se vuelve fea si además de la causa raíz tienes errores en el manejo de fallas de código.

Una forma que es fácil de usar, portátil y que apenas utiliza recursos sería capturar clases vacías.Sé que esto puede parecer extraño al principio, pero puede resultar muy útil.

Aquí hay un ejemplo que hice para otra pregunta que también se aplica a su pregunta: enlace

Además, puedes tener más de 1 captura:

try
{
   /* code that may throw exceptions */
}
catch (Error1 e1)
{
   /* code if Error1 is thrown */
}
catch (Error2 e2)
{
   /* code if Error2 is thrown */
}
catch (...)
{
   /* any exception that was not expected will be caught here */
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top