Puis-je annuler ou supprimer une commande atexit?
Question
Si je place atexit( fn );
sur la pile de sortie, il sera exécuté lorsque le se programme sort. Retours de main()
ou via exit()
Puis-je retirer de la pile?
Pourquoi est-ce que je veux ce faire, demandez-vous?
J'expérimentais avec un simple mécanisme de prise d'essai à l'aide atexit
, setjmp
et longjmp
. Il serait tout simplement parfait si je pouvais undo-atexit(fn);
-. Même si elle ne fonctionne que pour la dernière fonction enregistrée
Edit:
Suite à la suggestion de monoceres faire ma propre pile ...
La pile fonctionne uniquement avec un receveur d'exception pour l'instant.
void (*_catchFn[10])() = {0,0,0,0,0,0,0,0,0,0};
void _catch(){
if ( _catchFn[0] != 0 ){
(_catchFn[0])();
}
}
void _addCatch( void (*fn)() ){
_catchFn[0]=fn;
}
void _remCatch( void (*fn)() ){
_catchFn[0]=0;
}
void test(){
jmp_buf env;
void catch(){ // we get here after an exit with a registered catch
longjmp(env,1); // return to the line marked except...
// that first will get the value 1
}
int first = setjmp( env); // ** return here **
fprintf( stderr , "test: After setjmp. first=%d\n" , first );
if( first == 0 ){ // try this code
_addCatch(catch); // register the catch function to 'catch' the exit
fprintf( stderr , "test: Before CHECK\n" );
// CHECK something and something bad happens and it exits
exit(1); // like this
fprintf( stderr , "test: After CHECK - THIS SHOULD NEVER BE SEEN AFTER AN EXCEPTION.\n" );
}else{
fprintf( stderr , "test: After longjmp return. first=%d\n" , first );
}
_remCatch( catch);
fprintf( stderr , "test: IT WORKED!\n");
exit(1); // exit again to see if we are safe
}
int main(){
atexit( _catch ); // register my global exception stack
test();
}
La solution
Pourquoi ne pas construire votre propre pile que vous appelez à partir d'une seule fonction atexit ()? De cette façon, vous pouvez manipuler la pile tout ce que vous voulez.
Autres conseils
Non, vous ne pouvez pas le faire, mais vous pouvez utiliser l'indicateur global de sorte que votre gestionnaire de sortie ne sera rien faire si le drapeau est réglé.
Vous pouvez aussi appeler _Exit()
(C99) -. Il effectuera la procédure de sortie normale (fermer tous les descripteurs ouverts, envoyer tous les signaux nécessaires et parents / enfants) mais ne gestionnaire d'appels de sortie