Если я помещаю atexit( fn );
на стопке выхода это будет выполняться, когда программа выйдет: возвраты из main()
или через exit()
.
Я могу удалить его из стека?
Почему я хочу сделать это, Вы спрашиваете?
Я экспериментировал с простым использованием механизма выгоды попытки atexit
, setjmp
и longjmp
. Это было бы просто прекрасно, если я мог undo-atexit(fn);
- даже если это только работало бы на последнюю зарегистрированную функцию.
Править:
Предложение следующих моновосковин для создания моего собственного стека...
Стек только работает с одним ловцом исключения на данный момент.
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();
}
Почему бы не создать свой собственный стек, который вы вызываете из единственной функции atexit ()? Таким образом, вы можете манипулировать стеком сколько угодно.
Нет, вы не можете этого сделать, но вы можете использовать глобальный флаг, поэтому ваш обработчик выхода не будет делать ничего, если этот флаг установлен.
В качестве альтернативы вы можете вызвать _Exit ()
(C99) - он выполнит обычную процедуру выхода (закроет все открытые дескрипторы, отправит все необходимые сигналы и родительский / дочерний элемент), но не вызовет обработчик выхода.