Posso desfazer ou remover um comando Atexit?
Pergunta
Se eu colocar atexit( fn );
Na pilha de saída, ela será executada quando o programa sair: retornar main()
ou via exit()
.
Posso removê -lo da pilha?
Por que eu quero fazer isso, você pergunta?
Eu estava experimentando um simples mecanismo de tentativa usando atexit
, setjmp
e longjmp
. Seria perfeito se eu pudesse undo-atexit(fn);
- Mesmo que funcionasse apenas para a última função registrada.
Editar:
Após a sugestão de Monoceres para fazer minha própria pilha ...
A pilha funciona apenas com um apanhador de exceção por enquanto.
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();
}
Solução
Por que não construir sua própria pilha que você chama de uma função ATEXIT () única? Dessa forma, você pode manipular a pilha o quanto quiser.
Outras dicas
Não, você não pode fazer isso, mas pode usar o sinalizador global para que seu manipulador de saída não faça nada se o sinalizador estiver definido.
Alternativamente, você pode ligar _Exit()
(C99) - Ele executará procedimento de saída normal (feche todos os descritores abertos, envie todos os sinais necessários e pais/filhos), mas não chamará o manipulador de saída.