Newsgroup: it.comp.lang.c++
Titolo: exit() e distruttori

Ho notato che quando un programma termina con una chiamata ad exit(), oppure 
quando riceve un segnale SIGTERM, i distruttori degli oggetti costruiti NON 
vengono richiamati. Eppure nel manuale c'č scritto che tali funzioni 
terminano un programma "gracefully"...:)
C'č modo di risolvere questo problema ? Io avevo pensato di risolvere 
lanciando un eccezione, diciamo di tipo "exit", catturata soltanto da un 
gestore alla fine del main... potrebbe funzionare ? Esiste una soluzione 
piů standard ?
-- 
LF

 più standard ?
per risolvere tale problema devi gestire le eccezioni in modo
appropriato.
la propagazione di un'eccezione infatti provoca lo "srotolamento dello
stack"
che chiama i distruttori per ogni livello di visibilita'.
la funzione exit() invece non puo' chiamare i distruttori della 
funzione chiamante ne' di quelle piu' esterne ( di cui non conosce
l'esistenza).
attenzione pero' ad eccezioni non intercettate ed inaspettate........

 
Ma sei sicuro? Io uso exit() e i distruttori vengono chiamati 
correttamente..certo se hai allocato degli oggeti dinamicamente, tocca a te 
farne il delete, exit() non lo fa di certo.
Pero' per gli oggetti statici, il distruttore viene chiamato
Per lo meno, con MSVC6 funziona cosi'

 correttamente..
Io uso gcc 3.2 sotto linux, ed in questo esempio il distruttore non viene 
chiamato:
#include <cstdlib>
#include <iostream>
using namespace std;
class oggetto {
public:
  oggetto() {cout << "COSTRUTTORE" << endl;}
  ~oggetto() {cout << "DISTRUTTORE" << endl;}
};
int main() {
  oggetto prova;
  exit(0);
}
A te invece lo richiama ? Naturalmente in questo caso sostituendo la exit() 
con un return si risolve tutto...
-- 
LF

 appropriato.
Si, infatti ho parzialmente risolto usando le eccezioni. Il problema rimane 
nell'intercettare il segnale SIGTERM, infatti dal signal handler se lancio 
un eccezione il programma chiama abort()...:(
Qualche suggerimento ?
-- 
LF

 con un return si risolve tutto...
Questo e' quello che dice lo standard in proposito: "Calling the
function
void exit(int);
declared in <cstdlib> (18.3) terminates the program without leaving
the current block and hence without destroying any objects with
automatic storage duration (12.4). If exit is called to end a program
during the destruction of an object with static storage duration, the
program has undefined behavior."
Mi sembra perfettamente chiaro, no?
Ciao,
Nicola

...

non ho capito cosa stai facendo, puoi spiegarmi meglio????
di default abort() e' chamata da std::terminate() che e' a sua volta
invocata quando:
           un'eccezione non viene intercettata
           il gestore delle eccezioni trova lo stack in uno stato
inconsistente
           un distruttore durante lo srotolamento dello stack lancia
un'altra eccezione
 
             analogamente forse dovrebbe succedere nel caso di
eccezioni inattese...

LF <l...@lf.invalid> wrote in news:bmhqj6$v0m$
1...@lacerta.tiscalinet.it
:

Hai ragione, in questo caso non viene chiamato il distruttore di oggetto.
Pero' se invece che dichiararlo come variabile interna al main la 
dichiari come var globale, allora il distruttore viene chiamato.
Prob exit non chiama il distruttore delle vari locali alla fn che a sua 
volta chiama exit()

 non ho capito cosa stai facendo, puoi spiegarmi meglio????
(Premetto che sto sviluppando sotto Linux, quindi il codice seguente non č 
del tutto C++ standard)
Sto sviluppando un server che una volta avviato gira in background in 
seguito alla chiamata:
daemon(0,0);
Vorrei che quando il programma riceve il segnale di sistema SIGTERM 
(terminazione "pulita", a differenza di SIGKILL) faccia alcune operazioni 
prima di uscire: queste operazioni l'ho messe nei distruttori delle varie 
classi interessate.
Per intercettare il segnale SIGTERM uso:
signal(SIGTERM,uscita_pulita);
Il problema č, cosa metto nella funzione:
void uscita_pulita(int) {
  // exit(0) non funziona !!
  // throw "ESCI !!" richiama abort()
}
per fare in modo che i distruttori vengano chiamati ?
-- 
LF

 void exit(int);
Ecco, allora il GCC non ha colpe, mi pareva strano...:)
Suggerimenti per l'intercettazione del SIGTERM ?
-- 
LF

 per fare in modo che i distruttori vengano chiamati ?
In ambiente *nix, poche chiamate di sistema possono essere invocate
dall'interno di un signal handler senza determinare un comportamento
indefinito ('exit' non è una di queste, peraltro).
In generale la cosa più ragionevole è limitarsi a impostare un flag (di tipo
sig_atomic_t) e lasciare che la cosa venga gestita altrove. Tenderei a
credere che, anche nel tuo caso, questa sia la strada da seguire.
Max

 a credere che, anche nel tuo caso, questa sia la strada da seguire.
Uhm... perň se non sbaglio seguendo questo approccio devo nel ciclo 
principale ogni tanto controllare tale flag, giusto ? O ci sono altri 
metodi ?
-- 
LF

 
Se vuoi un clean-up pulito, con la chiamata dei distruttori e tutto il 
resto, non puoi risolvere la questione all'interno del signal handler, che 
potrebbe essere invocato in qualsiasi momento, interrompendo qualsiasi 
cosa. Devi necessariamente ritornare e gestire la cosa nel flusso di 
esecuzione normale del programma. 
Max