Pregunta

¿Cómo puedo detectar y manejar de manera eficiente los fallos de segmentación de C en una aplicación OSX Carbon?

Fondo: Estoy haciendo una aplicación de OSX Carbon. Debo llamar a una función de biblioteca de un tercero. Debido a problemas de subprocesos, la función puede bloquearse ocasionalmente, generalmente porque se está actualizando a sí misma desde un subproceso, y tiene algún puntero o controlador obsoleto internamente cuando lo consulto desde otro. La función es una caja negra para mí. Quiero poder llamar a la función pero poder " capturar " Si se ha estrellado y suministre un retorno alternativo. En Windows, puedo usar el simple compilador de Visual C e Intel C __try {} y __except.

/* Working Windows Example */
__try { x=DangerousFunction(y);}
__except(EXCEPTION_EXECUTE_HANDLER) {x=0.0;} /* whups, func crashed! */

Estoy tratando de hacer el mismo tipo de catch-crash para OSX. Estoy usando C puro en una aplicación muy grande. Llamo a la función millones de veces por segundo, por lo que la eficiencia también es muy importante. (¡Impresionante, la sobrecarga de Windows __try () es inmensamente pequeña!)

Esto es lo que he experimentado con:

1) Excepciones de C ++. No estoy seguro de si las excepciones de C ++ detectan los fallos de segfault. Y mi aplicación es actualmente C. Podría probar wrappers y #ifdefs para convertirlo en C ++, pero esto es mucho trabajo para la aplicación, y no creo que las excepciones de C ++ atrapen el bloqueo.

2) señal + setjump + longjmp. Pensé que esto funcionaría ... es para lo que está diseñado. Pero configuré mi controlador de errores SEGV [¡de hecho lo configuré para cada señal!] Y nunca se llama durante el bloqueo. Puedo probar manualmente (y tener éxito) al llamar a raise (SEGV). Pero los accidentes no parecen realmente llamarlo. Creo que las aplicaciones CFM NO tienen acceso a las señales BSD completas, solo un subconjunto, y que las aplicaciones Mach son necesarias para la Cosa Real.

3) MPSetExceptionHandler. No bien documentado Intenté establecer un controlador. Se compiló y corrió, pero no detectó la falla de seguridad.

¿Fue útil?

Solución

¿Está seguro de que no obtendrá un SIGBUS en lugar de un SIGSEGV?

Lo siguiente detecta a SIGBUS como causado al intentar escribir en la ubicación de memoria 0:

cristi:tmp diciu$ cat test.c

#include <signal.h>

static void sigac(int sig)
{
    printf("sig action here, signal is %d\n", sig);
    exit(1);
}

int main()
{
    (void)signal(SIGSEGV, sigac);
    (void)signal(SIGBUS, sigac);

    printf("Raising\n");
    strcpy(0, "aaksdjkajskd|");
}



cristi:tmp diciu$ ./a.out 
Raising
sig action here, signal is 10
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top