Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Anonymous

unregistriert

1

31.08.2004, 08:11

Exception startet destruktor

hallo,
beim lernen von exceptions ist mir folgender code in die hand gefallen und habe ihn abgetippt. leider wird automatisch beim erstellen des arrys, eine ausnahame auslöst -soweit ist auch noch alles ok -
aber dann:
sofort nach dem erstellen der ausnahme springt der compiler zurück in die main, will das programm beenden und startet den destruktor für die ausnahme. das programm strüzt ab.
könnte mir jemand hilfestellung geben?
bitte bitte erbarme mich einer meiner sorgen
mfg der dude ;-)


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
:

#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

}

2

31.08.2004, 12:42

Na also mich wundert`s nicht so sehr, hätte aber ehrlich gesagt auch nicht damit gerechnet. ANscheinend wird das Objekt erstellt, obwohl die Exception geworfen wird, dann soll es gelöscht werden, und der Pointer (pType) ist nicht initilisiert. Also wenn ich das richtig sehe ist der Programmablauf folgender:

1. erstellt ein 0 - Array

2. 0 - Exception wird geworfen -> kein Speicher mit new allokiert

3. Ausführung erreicht catch - Block, Gültigkeitsbereich der Variable wird verlassen-> Destruktoraufruf

4. Destruktor versucht Freigabe von nicht mit new allokierten (nämlich gar nicht allokierten) Speichers, das ist nicht erlaubt, denk ich. Wenn ich`s richtig gesehen hab, bleibt der Pointer uninitialisiert, wenn du ne Exception wirfst.


Vorschlag: Setze pType von Anfang an auf null und mach das delete im Destruktor davon abhängig (if pType != null delete[] pType), dann sollte denk ich nichts mehr schiefgehn.


Ich hoffe daran liegts, erscheint mir zumindest logisch, falls ich hier blödfug rede, immer druff! Hab leider grad keine Literatur hier um`s zu prüfen.

3

31.08.2004, 13:03

Ne haste schon richtig erkannt. Nur das kein 0-Array erzeugt wird. Es soll ein Array mit der Größe 8 erzeugt werden. Min. Größe ist aber 10. Also wird wohl die Exception Array::xTooSmall geworfen.

Der Pointer ist jedoch noch nicht Initialisiert und da delete & delete[] nicht darauf achten, beendet das OS das Programm mit der Fehlermeldung.


Ändere den Code wie folgt

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Konstruktor: pType wird mit NULL-Initialisiert!

Array::Array(int size): itsSize(size), pType(0)
{
    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;
}

Array::~Array()
{
   if(pType)
   {
        delete[] pType;
        pType = 0;       // Um ganz sicher zugehen ;)

   }
}

Dann sollte alles laufen :) Ich weis nicht wo du den Code her hast. Aber schreib dem jenigen, das er dies ganz schnell ändern soll.

Aber lass es dir ebenfalls ein gutes Beispiel sein, das zeigt wie wichtig die Initialisierung, besonders bei Zeigern, ist.
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

Patrick

Alter Hase

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

4

31.08.2004, 13:19

Bitte ersetz das <iostream.h> durch <iostream>. Das Thema wurde glaube ich schon genug durchgekaut ;D;D;D

[klugscheiß]benutz anstatt getch(); dies hier:

C-/C++-Quelltext

1
std::cin.get(); 


dann kannste auch die <conio.h> weglassen ;D [/klugscheiß]

Anonymous

unregistriert

5

31.08.2004, 15:13

[klugscheiß_zum_quadrat]

C-/C++-Quelltext

1
2
using namespace std;
//Wäre es so nicht noch perfekter???

[/klugscheiß_zum_quadrat]

anstatt so:

anstatt so:
std::cin.get();
nap ist das was ??


der dude :)

Patrick

Alter Hase

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

6

31.08.2004, 15:20

Zitat von »"Der Dude"«

[klugscheiß_zum_quadrat]

C-/C++-Quelltext

1
2
using namespace std;
//Wäre es so nicht noch perfekter???

[/klugscheiß_zum_quadrat]

anstatt so:

anstatt so:
std::cin.get();
nap ist das was ??


Nicht perfekter. Wenn du dich mehr mit Namespaces beschäftigst, wirst du verstehen warum ;)

std::cin.get(); << fast das selbe wie getch();

Anonymous

unregistriert

7

31.08.2004, 17:42

ach menno :-(
jetzt wusste ich mal was - aber auch egal.
mal ne frage, wieso soll es besser sein. da man doch meistens auch die standardfunktionen zugreift ist es doch besser diesen direkt in benutzung zu nehmen, oder?

DarthB

Treue Seele

Beiträge: 265

Beruf: Schüler

  • Private Nachricht senden

8

02.09.2004, 00:31

Naja stell dir halt mal vor du packst deine Engine in einen namespace und deine engine hat auch einen vector und schon wird anstatt der Vector von deiner engine der std::vector ausgewählt.

Aber solange man keinen anderen Namespace benutzt und ne etwas längere Konsolenanwendung schreibt kann man sich durch "using namespace std;" ne Menge arbeit sparen.

Ciao DarthB :huhu:
Jetzt hab ich auch ne Signatur! ;)

9

04.09.2004, 01:40

Im Prinzip ist es egal ob man nun std:: oder using namespace std; schreibt.

Der Vorteil am std:: ist es, dass man besser erkennen kann aus welchem Namespace der Code kommt. Wenn man mal mit mehr als 5 Namespaces zu tun hat, wird man es schätzen lernen nicht 20 using namespaces zu schreiben und keinen Überblick mehr zu haben, was steckt worin, sonder lieber den scope operator benutzen und den Überblick gewährleisten.

Aber generell bleibt es eine Geschmackssache!

Werbeanzeige