Ho una class con un distruttore definito dall’utente. Se la class è stata istanziata inizialmente, e quindi SIGINT viene emesso (usando CTRL + C in unix) mentre il programma è in esecuzione, verrà chiamato il distruttore? Qual è il comportamento di SIGSTP (CTRL + Z in unix)?
No, per impostazione predefinita, la maggior parte dei segnali causa un’uscita immediata e anormale del programma.
Tuttavia, è ansible modificare facilmente il comportamento predefinito per la maggior parte dei segnali.
Questo codice mostra come fare un segnale di uscire normalmente dal tuo programma, incluso chiamare tutti i soliti distruttori:
#include #include #include #include #include std::atomic quit(false); // signal flag void got_signal(int) { quit.store(true); } class Foo { public: ~Foo() { std::cout << "destructor\n"; } }; int main(void) { struct sigaction sa; memset( &sa, 0, sizeof(sa) ); sa.sa_handler = got_signal; sigfillset(&sa.sa_mask); sigaction(SIGINT,&sa,NULL); Foo foo; // needs destruction before exit while (true) { // do real work here... sleep(1); if( quit.load() ) break; // exit normally after SIGINT } return 0; }
Se esegui questo programma e premi control-C, dovresti vedere la parola "destructor" stampata. Siate consapevoli del fatto che le funzioni del vostro gestore di segnale (got_signal) dovrebbero raramente svolgere qualsiasi lavoro, tranne che impostare una bandiera e tornare tranquillamente, a meno che non si sappia davvero cosa si sta facendo.
La maggior parte dei segnali è catchable come mostrato sopra, ma non SIGKILL, non si ha il controllo su di esso perché SIGKILL è un metodo last-ditch per uccidere un processo in fuga, e non SIGSTOP che consente a un utente di congelare un processo a freddo. Nota che puoi catturare SIGTSTP (control-Z) se lo desideri, ma non è necessario se il tuo unico interesse per i segnali è il comportamento del distruttore, perché alla fine dopo un controllo-Z il processo verrà ritriggersto, continuerà a funzionare e uscirà normalmente con tutti i distruttori in vigore.
Se non gestisci questi segnali da solo, allora, no, i distruttori non vengono chiamati. Tuttavia, il sistema operativo recupererà tutte le risorse utilizzate dal programma al momento della sua conclusione.
Se desideri gestire autonomamente i segnali, sigaction
considerazione di verificare la funzione di libreria standard sigaction
.
Proviamolo:
#include #include class Foo { public: Foo() {}; ~Foo() { printf("Yay!\n"); } } bar; int main(int argc, char **argv) { sleep(5); }
E poi:
$ g++ -o test ./test.cc $ ./test ^C $ ./test Yay!
Quindi temo di no, dovrai prenderlo.
Per quanto riguarda SIGSTOP
, non può essere catturato e mette in pausa il processo fino a quando SIGCONT
viene inviato un SIGCONT
.