Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Ruft unlogischer weise den destruktor auf

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
30.08.2004, 22:18 Uhr
~Der Dude
Gast


hallo,
beim lernen von exceptions ist mir folgender code in die hand gefallen und habe ihn abgetippt. leider wird automatisch eines arrys, welches eine ausnahame auslöst sofort der destruktor aufgerufen.
könnte mir jemand hilfestellung geben?
bitte bitte erbarme mich einer meiner sorgen
mfg der dude ;-)


C++:

#include <iostream.h>
#include <conio.h>

const int DefaultSize = 10;

class Array
{
    public:
       // Konstruktoren
      Array(int itsSize = DefaultSize);
      Array(const Array &rhs);
      ~Array() { delete [] pType;}

      // Operatoren
      Array& operator=(const Array&);
      int& operator[](int offSet);
      const int& operator[](int offSet) const;

      // Zugriffsfunktionen
      int GetitsSize() const { return itsSize; }

      // Friend-Funktion
      friend ostream& operator<< (ostream&, const Array&);

      // Exception-Klassen definieren
      class xBoundary {};
      class xSize
      {
          public:
             xSize(int size):itsSize(size) {}
            ~xSize(){}
            int GetSize() { return itsSize; }
         private:
            int itsSize;
        };

      class xTooBig : public xSize
      {
          public:
             xTooBig(int size):xSize(size){}
      };

       class xTooSmall : public xSize
      {
         public:
            xTooSmall(int size):xSize(size){}
      };

      class xZero  : public xTooSmall
      {
         public:
            xZero(int size):xTooSmall(size){}
      };

      class xNegative : public xSize
      {
         public:
            xNegative(int size):xSize(size){}
      };

    private:
         int *pType;
         int  itsSize;
};


Array::Array(int size):
itsSize(size)
{
    if (size == 0)
       throw xZero(size);
   if (size > 30000)
       throw xTooBig(size);
   if (size <1)
       throw xNegative(size);
   if (size < 10)                                                          //Hier wird die ausnahme erstellt
       throw xTooSmall(size);

   pType = new int[size];
    for (int i = 0; i<size; i++)
       pType[i] = 0;
}


int& Array::operator[] (int offSet)
{
    //int size = GetitsSize();
   if (offSet >= 0 && offSet < GetitsSize())
       return pType[offSet];
   throw xBoundary();
   // return pType[0];
}

const int& Array::operator[] (int offSet) const
{
    // int size = GetitsSize();
   if (offSet >= 0 && offSet < GetitsSize())
       return pType[offSet];
   throw xBoundary();
   //   return pType[0];
}

int main()
{


    try
   {
       Array intArray(8);
      for (int j = 0; j< 100; j++)
      {
          intArray[j] = j;
         cout << "intArray[" << j << "] OK..." << endl;
      }
   }
   catch (Array::xBoundary)
   {
       cout << "Kann Ihre Eingabe nicht verarbeiten.\n";
   }
   catch (Array::xZero theException)
   {
       cout << "Array von null Objekten angefordert." << endl;
      cout << "Empfangen " << theException.GetSize() << endl;
   }
   catch (Array::xTooBig theException)
   {
       cout << "Dieses Array ist zu groß..." << endl;
      cout << "Empfangen " << theException.GetSize() << endl;
   }
   catch (Array::xTooSmall theException)
   {
       cout << "Dieses Array ist zu klein..." << endl;
      cout << "Empfangen " << theException.GetSize() << endl;
   }
   catch (...)
   {
       cout << "Etwas ist schiefgelaufen. Keine Ahnung, was!\n";
   }

   cout << "Fertig.\n";

       getch();

   return 0;

//geht zu return - leider keine ahnung warum - nachdem das ausnahmeobjekt erstellt wurde //und will den destruktor aufrufen. dieses führt zu einer fehlermeldung und das programm //stürzt ab
}



 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
30.08.2004, 23:38 Uhr
virtual
Sexiest Bit alive
(Operator)


Der Code ist generell erstmal nicht falsch, aus der Verwendng von getch() und conio.h schließe ich, daß Du irgendwas Windowsmäßiges als Compiler laufen läßt. Was genau?
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
31.08.2004, 08:01 Uhr
~Der Dude
Gast


ich abeite mit dem borland compiler
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
31.08.2004, 11:24 Uhr
(un)wissender
Niveauwart


Es wird welcher Destuktor aufgerufen?
Der des Arrays?
Du musst das Array auch außerhalb des try-Blocks deklarieren, da es nur in diesem gültig ist.
Der Destruktor wird also zu recht aufgerufen!


C++:
int main()
{

Array *intArray = 0;
    try
   {
      intArray = new intArray(8);
      for (int j = 0; j< 100; j++)
      {
          (*intArray)[j] = j;
         cout << "intArray[" << j << "] OK..." << endl;
      }
   }
   catch (Array::xBoundary)
   {
       cout << "Kann Ihre Eingabe nicht verarbeiten.\n";
   }
   catch (Array::xZero theException)
   {
       cout << "Array von null Objekten angefordert." << endl;
      cout << "Empfangen " << theException.GetSize() << endl;
   }
   catch (Array::xTooBig theException)
   {
       cout << "Dieses Array ist zu groß..." << endl;
      cout << "Empfangen " << theException.GetSize() << endl;
   }
   catch (Array::xTooSmall theException)
   {
       cout << "Dieses Array ist zu klein..." << endl;
      cout << "Empfangen " << theException.GetSize() << endl;
   }
   catch (...)
   {
       cout << "Etwas ist schiefgelaufen. Keine Ahnung, was!\n";
   }

   cout << "Fertig.\n";
   delete intArray;
       getch();

   return 0;




Das sollte es tun, mal so in Forum getippt.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
31.08.2004, 12:03 Uhr
~Der Dude
Gast


vielen dank erstmal an den (un)wissenden :-),
leider verstehe ich das noch nicht ganz wieso die variable zerstört wird und der zeiger nicht. könntest du es mir vielleicht etwas genauer erklären - da ich nicht verstehe wieso die variable zerstört wird :-(. weil ob ich den speicher aus dem heap oder stack nehme dürfte doch keinen unterschied machen, oder?

und noch einen frage:
ist folgenden schreibweise auch zulässig?

C++:
(*intArray)[j] = j; //Deine Version
intArray->[j] = j; //Auch richtig?



würde mcih sehr über eine antwort freuen, der dude :-)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
31.08.2004, 13:17 Uhr
virtual
Sexiest Bit alive
(Operator)


@(un)wissender:
Nein, das ist mnicht korrekt: im Constructor von Array im try Block wird die Exception geworfen, daher wird niemals der Destructor aufgerufen. Dh Code wie zB dieser ist immer Speicherleckverdächtig:

C++:
class X
{
    char* s1;
    char* s2;
public:
     X() { s1 = new char[1024]; s2 = new char[1024]; }
     ~X() { delete[] s1; delete[] s2; }
};


Wenn die Allocation von s1 gut geht, bei der Allokation von s2 was schief geht, wird nie und nimmer der dtor aufgerufen und daher leakt das Porgramm, weil s1 niemals freigegeben wird. Richtig wäre da schon eher:

C++:
class X
{
    char* s1;
    char* s2;
public:
     X() :s1(NULL), s2(NULL) {
         try
         {
             s1 = new char[1024];
             s2 = new char[1024];
         }
         catch(...)
         {
             delete [] s1;
             delete [] s2;
             throw;
         }
     }
     ~X() { delete[] s1; delete[] s2; }
};



Würde in Dudes Beispiel tatsächlich der dtor aufgerufen, dann würde das Programm mit 99% Prozentiger Wahrscheinlichkeit abstürzen, weil die Exception im ctor geworfen wird, bevor der member pType initialisiert wird. Würde nun der dtor aufgerufen, würde ein delete auf einen ungültigen Zeiger gemacht.

Hier noch ein kleines Beispiel zum Beleg meiner Aussage (ungetestet):

C++:
#include <iostream>
#include <stdexcept>

struct Throw
{
    Throw() { std::cerr<<"ctor"<<std::endl; throw std::runtime_error("Error"); }
    ~Throw() { std::cerr<<"dtor"<<std::endl; }
};

int main()
try {
    Throw t;
}
catch(std::exception& e) {
    std::cerr<<e.what()<<std::endl;
}


Ich würde die Ausgabe

Code:
ctor
Error


erwarten. Falsch wäre die Ausgabe

Code:
ctor
dtor
Error


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 31.08.2004 um 13:18 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
31.08.2004, 13:23 Uhr
virtual
Sexiest Bit alive
(Operator)


@Dude
Die Frage wann was zerstört wird läßt sich ganz einfahc beantworten:
1. Alles was du mit new erzeugst, wird nur durch delete zerstört.
2. Alles was nicht mit new erzeugt wird, wird dann zerstört, wenn der umgebende Block ('{' und '}') verlassen wird. Gobale Variablen werden nach verlassen der Funktion main zerstört.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
31.08.2004, 13:40 Uhr
(un)wissender
Niveauwart


Ah, klar der dtor wird bei nicht erfolgreicher Erstellung nicht aufgerufen, habe ich übersehen.
Allerdings produziert meine Version definitiv kein Speicherleck, da es sicher ist einen Null-Zeiger zu löschen und auch keine Allokation sonst stattfindet.
Der dtor wird also nicht aufgerufen, erst wenn der try-Block verlassen wird, wird intArray, wenn erfolgreich erstellt, zerstört.
(Kann glaube ich auch erst am Ende von main passieren, genau weiß ich das nicht).


C++:
(*intArray)[j] = j; //Deine Version
intArray->[j] = j; //Auch richtig?
intArray->operator[](j) = j //so geht es


--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
31.08.2004, 15:13 Uhr
~Der Dude
Gast


was bedeutet "dtor"?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
31.08.2004, 16:21 Uhr
virtual
Sexiest Bit alive
(Operator)


dtor = Destructor
ctor = Constructor
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: