Newsgroup: it.comp.lang.c++
Titolo: Schianto sul distruttore

Qualche persona caritatevole, potrebbe spiegarmi perchè questo programmino 
mi si schianta sul distruttore?
Dove sbaglio?
Grazie mille
Agos
#include <iostream>
#include <string>
using namespace std;
class OutOfMemory
{
   public:
      OutOfMemory(char *);
      ~OutOfMemory();
     char* GetString() { return itsString; }
   private:
      char* itsString;
};
// destructor, frees allocated memory
OutOfMemory::~OutOfMemory()
{
   delete [] itsString;
   cout << "\tStringa destructor\n";
}
//costruttore
OutOfMemory::OutOfMemory(char * theType)
{
   itsString = new char[80];
   char warning[] = "Out Of Memory! Can't allocate room for: ";
   strncpy(itsString,warning,60);
   strncat(itsString,theType,19);
}
int main()
{
   try
   {
      int *myInt = new int;
      if (myInt != 0) // != è per far funzionare l'eccezione
      throw OutOfMemory("int");
   }
   catch (OutOfMemory& eccezione)
   {
      cout << "Unable to allocate memory " << eccezione.GetString() << "\n";
   }
   return 0;
} 

 
Definisci un costruttore copia appropriato per OutOfMemory. Quello
sintetizzato dal compilatore effettua la semplice copia del puntatore
'itsString' con l'effetto di lasciare due instanze con lo stesso valore, su
cui entrambe invocheranno 'delete[]'.
Max

 Max

> Max

>> Max

 ha scritto nel messaggio 
news:die66h$mtu$1...@newsreader.mailgate.org...


 ha scritto nel messaggio 
news:434acc41$0$29560$4faf...@reader1.news.tin.it...


 l'oggetto eccezione dentro un blocco e poi era fuori scope per la catch ?
No. E' perfettamente lecito lanciare un oggetto temporaneo. Quello che 
mancava era un appropriato costruttore copia.
Max

 


  strcpy(itsString,const_cast <OutOfMemory &>(f).GetString());
Qui ora il const_cast non serve più, perchè GetString ora è un membro 
const. Ad ogni modo, in questa funzione puoi accedere direttamente a 
f.itsString. Inoltre, dovresti constrollare che non sia NULL, pena 
comportamento indefinito di strcpy.
E per finire: perché non usi std::string anziché reinventare la ruota?
Max

 
Dalle spiegazini e da quello che so(poco) hai centrato il punto.
Con la tua vecchia implementazione(sbagliata), l'eccezione creava una 
copia dell'oggetto ..ma in un modo fallace.
Ovvero copiava in un altro oggetto il link(puntatore) alla stessa stringa.
Quindi il risultato finale e' che, dato che sia l'oggetto originale che 
la copia nella catch vengono prima o poi distrutti, il "delete " viene 
applicato due volte su una stringa(puntatore) che punta la stessa zona 
di memoria.
Quindi una volta va bene e alla seconda..BANG.. errore.
Questo newsgroup e' per me una fonte di esercizi visto che sto 
"imparando il c++", spero quindi che le mie osservazioni e sforzi di 
comprensione siano utili e pertinenti.
Se non ho fatto centro aspetto bachettate istruttive.
Saluti


Ritengo che allocare una nuova stringa risolvera' agevolmente il problema.

 ha scritto nel messaggio 
news:s02gid...@news.tana.net...


 nulla) chiaro il perchè.
Usi sempre il stesso compilatore? Colla stessa commanda?
Formalemente: hai costruito un temporario (sullo stack), che il
compilatore copia in una zona sicura primo di risalire lo stack.
Ma la norma autorizza il compilatore a supprimare la copia, e a
costruire la prima volta direttamente nella sua zona. Se lo fà
dipende del compilatore e deglia opzioni di optimisazione.
È anche possibile che fà l'optimisazione solo se c'è un
costrutore di copià non triviale.
Invecci, c'è una cosa che non capisco io. Se c'è un'eccezione
perche non c'è abbastanza memoria, cosa si passa allora di new
nel suo costrutore? Non sarebbe megliore :
    class OutOfMemory
    {
        //  ...
    private:
        char                itsString[ 80 ] ;
    } ;
--
James Kanze                                           GABI Software
Conseils en informatique orientée objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, 
+33 (0)1 30 23 00 34

cui entrambe invocheranno 'delete[]'.
Scusate ma io ho un dubbio .
L'oggetto invocato dalla throw  e' all'interno della funzione main e'
al gestore viene solo passato un "riferimento" mi sembra e non una
nuova copia dell'oggetto . Quindi l'oggetto dovrebbe venir distrutto
solo una volta e all'uscita della funzione main .

 solo una volta e all'uscita della funzione main .
Da quel che ne so da come funzionano le eccezzioni.
Throw come prima cosa crea una copia dell'oggetto, e il riferimento a 
->tale copia<- viene fornito alla catch.
O almeno cosi' ho capito...

>    } ;
==================================================
Si sarebbe meglio, ma quello che ho fatto era per provare il distruttore con 
un puntatore
perchè l'esempio da cui ho tratto questo codice non aveva messo il 
distruttore pur
allocando con una new una stringa.

>    } ;


>    } ;


Fabiano wrote:



In principe hai ragione. Solo, la norma permette certe
optimisazioni, anche se cambiano la semantica del programma. È
dunque possibile ch'il costruttore viene chiamato direttamente
sul oggetto finale, senza copia.


 
Ho capito, dipende da come si comporta il compilatore??
Speravo che almeno in questo caso si seguisse la "regola" :-(

 Speravo che almeno in questo caso si seguisse la "regola" :-(
Una cosa sola è richiesta: se non c'è un costruttore di copià
accessibile, è un'errore, e il compilatore deve dirla. Ma dopo,
può utilisare il costruttore di copia o non, come vuol.


 ha scritto nel messaggio 
news:1129292778....@g14g2000cwa.googlegroups.com...


 memoria ed il programma??
Non hai capito. Quello che diceva James č che quando passi a throw  un 
oggetto temporaneo questo deve disporre di un csotruttore copia accessibile 
(non importa se sia quello sintitetizzato dal compilatore o sia definito 
dall'utente). Soddisfatto questo requisito, il compilatore puņ eliminare la 
copia costruendo un unico oggetto in una locazione idonea.
Max