Domanda

Come posso rilevare e gestire in modo efficiente i guasti di segmentazione da C in un'applicazione OSX Carbon?

Background: sto realizzando un'applicazione OSX Carbon. Devo chiamare una funzione di libreria da una terza parte. A causa di problemi di threading, la funzione può occasionalmente arrestarsi in modo anomalo, di solito perché si sta aggiornando da un thread e ha un puntatore o un handle internamente non aggiornati mentre lo interrogo da un altro. La funzione è una scatola nera per me. Voglio poter chiamare la funzione ma essere in grado di "catturare" se si è bloccato e fornire un ritorno alternativo. In Windows, posso usare il semplice compilatore Visual C e Intel C __try {} e __except.

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

Sto cercando di creare lo stesso tipo di crash-catcher per OSX. Sto usando C puro su un'applicazione molto grande. Chiamo la funzione milioni di volte al secondo, quindi anche l'efficienza è molto importante. (Sorprendentemente, l'overhead di Windows __try () è incredibilmente piccolo!)

Ecco cosa ho sperimentato:

1) Eccezioni C ++. Non sono sicuro che le eccezioni C ++ catturino gli arresti anomali. E la mia app è attualmente C. Potrei provare wrapper e #ifdefs per renderlo C ++ ma questo è molto lavoro per l'app, e non credo che le eccezioni C ++ colpiranno il crash.

2) segnale + setjump + longjmp. Ho pensato che avrebbe funzionato ... è quello per cui è stato progettato. Ma ho impostato il mio gestore degli errori SEGV [in effetti l'ho impostato per ogni segnale!] E non viene mai chiamato durante l'incidente. Posso testare manualmente (e riuscire) quando si chiama rilancio (SEGV). Ma i crash non sembrano in realtà chiamarlo. Ritengo che le applicazioni CFM NON abbiano accesso a tutti i segnali BSD, solo un sottoinsieme e che le applicazioni Mach siano necessarie per la cosa reale.

3) MPSetExceptionHandler. Non ben documentato. Ho tentato di impostare un gestore. Si è compilato e funzionato, ma non ha catturato il segfault.

È stato utile?

Soluzione

Sei sicuro di non avere un SIGBUS piuttosto che un SIGSEGV?

Il seguito cattura SIGBUS come causato dal tentativo di scrivere nella posizione di 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top