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