Zum Inhalt springen

Heapfreigabe


mars12

Empfohlene Beiträge

Habe eine Klasse Matrix geschrieben, die folgendermaßen aussieht:

class CZeile 

{ 

protected: 

[INDENT]double *z; 

int size; [/INDENT]


public: 

[INDENT]~CZeile(void) {delete [] this->z}; 

CZeile(int s){this->size = s; this->z = new double[s];} [/INDENT]


} 


class CMatrix:public CZeile 

{ 

protected: 

[INDENT]CZeile **mat; //Zeiger auf "Zeilen"-Vektor 

int lines, cols; //Zeilen- und Spaltenzahl [/INDENT]



public: 

[INDENT]~CMatrix(void) 

{ 

[INDENT]for (int i = 0; i < this->lines; i++) 

{


[INDENT][/INDENT]

[INDENT]delete this->mat[i]; [/INDENT]


} [/INDENT]

[INDENT][/INDENT][INDENT]delete[] this->mat; [/INDENT]


} [/INDENT]

[INDENT]CMatrix(int z, int s, double wert) 

{ 

[INDENT]this->lines = z; 

this->cols = s; 

this->mat = new CZeile*[this->lines]; //Vektor fuer Zeiger auf Zeilenvektoren 

int i, j; 

for (i = 0; i < this->lines; i++) //Zeilenvektoren: 

{ 

[INDENT]this->mat[i] = new CZeile(this->cols); //Speicher reservieren [/INDENT]


[INDENT]for (j = 0; j < this->cols; ++j) 

{ 

[INDENT](*this)[i][j] = wert; //und Werte kopieren 

[/INDENT]
}[/INDENT]}[/INDENT]

} [/INDENT]} 

Soweit so gut, Matrix anlegen und damit arbeiten funktioniert alles, aber wenn ich im Debugmodus das Programm beenden möchte und den Destruktor aufrufe, kommt folgende Fehlermeldung:

Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffff9.

Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffff9.

Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffffa.

Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffffa.

Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffffb.

Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffffb.

HEAP[test21.exe]: Invalid Address specified to RtlFreeHeap( 00030000, 7C958FB7 )

Unbehandelte Ausnahme bei 0x7c91120e in test21.exe: Benutzerhaltepunkt.

Das Programm "[2496] test21.exe: Systemeigen" wurde mit Code 0 (0x0) beendet.

Habe schon herausgefunden, dass die Adresse 7C958FB7 das Element mat (also bei delete[] this->mat) ist. Dann wird der Destruktor von CZeile aufgerufen und es knallt.

Programmier noch nicht so lang, vielleicht kann mir das jemand erklären? Versteh soweit schon, dass ich auf Speicher zugreife, den es offensichtlich nicht mehr gibt, aber wo in meinem Code soll der Fehler liegen?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also das sieht doch alles sehr komisch aus.

Warum leitest du CMatrix von CZeile ab?

Warum ist mat ein CZeile**? So wie ich das sehe willst du ein CZeile*, das andere würde dir nur was bringen wenn du statt


this->mat[i] = new CZeile(this->cols);
[/PHP]

sowas

[PHP]
this->mat[i] = new CZeile[15];

machen würdest und damit im Prinzip ein dreidimensionales Array aus double Werten schaffen würdest.

Das hier


(*this)[i][j] = wert; //und Werte kopieren
[/PHP]

ist mir auch nicht so ganz geheuer und ich würde nicht vermuten das das definiertes Verhalten versucht, aber auf alle Fälle ist es nicht schön.

Wozu brauchst du eigentlich CZeile und machst nicht einfach ein double** in CMatrix?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Der Code lässt sich so überhaupt nicht kompilieren. Erstens hat CZeile keinen Defaultkonstruktor, und zweitens hat weder CMatrix noch CZeile einen operator[]. Da sind noch andere Fehler drin, die nahelegen, dass mars12 hier versucht hat, "Beispielcode" zu zeigen.

Das eigentliche Problem vermute ich darin, dass hier vergessen wurde, die Regel der großen Drei zu befolgen:

Wenn eine Klasse eines dieser drei hat:

- Nichttrivialer Destruktor

- Copykonstruktor

- Copy-Zuweisungsoperator

Dann braucht sie alle drei.

Link zu diesem Kommentar
Auf anderen Seiten teilen

OK, hatte nicht meinen kompletten Code geschrieben, da ich dachte das sprengt den Rahmen. Hier noch einmal:

class CZeile
{
protected:
double *z; //Zeiger auf Zeile
int size; //Groesse der Zeile

public:
CZeile(void); //Konstruktor
virtual ~CZeile(void); //Destruktor
CZeile(int s); //parametrisierter Konstruktor
double& operator[](int i); //prueft den Indexwert auf Gueltigkeit
const double& operator [](int i) const; //prueft den Indexwert auf Gueltigkeit
virtual void print(void); //Bildschirmausgabe
};

CZeile::CZeile(void)
{
}

CZeile::~CZeile(void)
{
delete [] this->z;
}

CZeile::CZeile(int s)
{
this->size = s;
this->z = new double[s];
}

double& CZeile::operator[](int i)
{
if (i < 0 || i > this->size)
{
throw out_of_range("Spaltenindex: Out of Range\n");
}
return this->z[i];
}

const double& CZeile::operator [](int i) const
{
if (i < 0 || i > this->size)
{
throw out_of_range("Spaltenindex: Out of Range\n");
}
return this->z[i];
}

void CZeile::print(void) //Bildschirmausgabe
{
}


class CMatrix :
public CZeile
{
protected:
CZeile **mat; //Zeiger auf "Zeilen"-Vektor
int lines, cols; //Zeilen- und Spaltenzahl
long int itsSum; //Summe

public:
CMatrix(void); //Konstruktor
~CMatrix(void); //Destruktor
CMatrix(int z, int s, double wert); //parametrisierter Konstruktor
CMatrix(int z, int s); //parametrisierter Konstruktor
int getLines(void);//gibt die Zeilenanzahl zurueck
int getCols(void); //gibt die Spaltenanzahl zurueck
const CZeile& operator[] (int i) const;//prueft den Indexwert auf Gueltigkeit
CZeile& operator[](int i);//prueft den Indexwert auf Gueltigkeit
CMatrix& operator=(const CMatrix&); //Einfache Zuweisung
CMatrix& operator+=(const CMatrix&);//Addition zweier Matrizen und Zuweisung
virtual void print(); //Bildschirmausgabe
void setWert(int z, int s, double WertTmp);//traegt Wert an bestimmte Stelle in Matrix ein
long int sum(void); //bildet Summe der Matrix
double getWert(int z, int s); //gibt Wert an bestimmter Stelle in Matrix zurueck
CMatrix(const CMatrix& m);//Copy-Konstruktor
};


CMatrix::CMatrix(void)
{
}

CMatrix::~CMatrix(void)
{
for (int i = 0; i < this->lines; i++)
{
delete this->mat[i];
}
delete[] this->mat;
}

CMatrix::CMatrix(int z, int s, double wert)
{
this->lines = z;
this->cols = s;
this->mat = new CZeile*[this->lines]; //Vektor fuer Zeiger auf Zeilenvektoren
int i, j;
for (i = 0; i < this->lines; i++) //Zeilenvektoren:
{
this->mat[i] = new CZeile(this->cols); //Speicher reservieren
for (j = 0; j < this->cols; ++j)
{
(*this)[i][j] = wert; //und Werte kopieren
}
}
}

CMatrix::CMatrix(int z, int s)
{
this->lines = z;
this->cols = s;
this->mat = new CZeile*[this->lines];
for (int i = 0; i < this->lines; i++)
{
this->mat[i] = new CZeile(this->cols);
}
}

int CMatrix::getLines(void)
{
return this->lines;
}

int CMatrix::getCols(void)
{
return this->cols;
}

CZeile& CMatrix::operator[](int i)
{
if(i < 0 || i > this->lines)
{
throw out_of_range("Zeilenindex: Out of Range\n");
}
return *mat[i];
}

const CZeile& CMatrix::operator[](int i) const
{
if(i < 0 || i > this->lines)
{
throw out_of_range("Zeilenindex: Out of Range\n");
}
return *mat[i];
}


CMatrix& CMatrix::operator=(const CMatrix& m)
{
int i, j; //Alten Speicher freigeben
for (i = 0; i < this->lines; i++)
{
delete[] this->mat[i];
}
delete[] this->mat;
this->lines = m.lines; //Zeilen
this->cols = m.cols; //Spalten
this->mat = new CZeile*[this->lines]; //Vektor fuer Zeilenvektoren
for (i = 0; i < this->lines; ++i) //Zeilenvektoren
{
this->mat[i] = new CZeile(this->cols); //Speicher reservieren
for (j = 0; j < this->cols; ++j)
{
(*this)[i][j] = m[i][j]; //Werte kopieren
}
}
return *this;
}


CMatrix& CMatrix::operator+=(const CMatrix& m)
{
int i, j;
if (this->cols == m.cols && this->lines == m.lines)
{
for (i = 0; i < this->lines; ++i)
{
for (j = 0; j < this->cols; ++j)
{
(*this)[i][j] += m[i][j];
}
}
}
return *this;
}

void CMatrix::print() //Bildschirmausgabe
{
for (int i = 0; i < this->lines; i++)
{
for (int j = 0; j < this->cols; ++j)
{
cout << (*this)[i][j] << " ";
}
cout << endl;
}
}

void CMatrix::setWert(int z, int s, double WertTmp)
{
(*this)[z][s] = WertTmp; //und Werte kopieren
}

long int CMatrix::sum(void)
{
this->itsSum = 0; //Wert zurueck setzen
int i, j;
for (i = 0; i < this->lines; i++)
{
for (j = 0; j < this->cols; ++j)
{
this->itsSum = this->itsSum + (*this)[i][j];
}
}
return this->itsSum;
}

double CMatrix::getWert(int z, int s)
{
return (*this)[z][s];
}

CMatrix::CMatrix(const CMatrix& m)
{
int i, j;
this->lines = m.lines; //Zeilen
this->cols = m.cols; //Spalten
this->mat = new CZeile*[this->lines]; //Vektor fuer Zeilenvektoren
for (i = 0; i < this->lines; ++i) //Zeilenvektoren
{
this->mat[i] = new CZeile(this->cols); //Speicher reservieren
for (j = 0; j < this->cols; ++j)
{
(*this)[i][j] = m[i][j]; //Werte kopieren
}
}
}
[/PHP]

Die "grossen Drei" sind doch richtig implementiert, oder nicht? Programmier noch nicht so lange und finde das mit den Zeigern auf Zeiger schon ziemlich tricky. Irgendeiner zeigt ins Nirvana. Wäre dankbar, wenn mir jemand helfen könnte.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das Problem ist, was Guybrush Threepwood bereits erwähnt hat. CMatrix erbt von CZeile, was totaler Blödsinn ist. Damit enthält jedes CMatrix-Objekt ein CZeile-Objekt. Da CZeile aber keinen sauberen Default-Konstruktor hat, bleibt der z-Member dieses Objekts uninitialisiert. Und wenn ein CMatrix-Objekt zerstört wird, wird auch der Basisklassendestruktor ausgeführt. Der ruft dann delete auf einen unitialisierten Zeiger auf -> Peng.

Übrigens, CZeile braucht auch Copykonstruktor und Copy-Zuweisungsoperator.

Und überhaupt wäre das ganze mit std::vector viel, viel einfacher. ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Verstehe. Habe jetzt mal versucht das ohne CZeile und mit double ** zu implementieren, aber wie Du schon sagtest, ist das auch nicht so ganz einfach. Jetzt funktioniert nämlich mein operator [] nicht mehr. Wie könnte das denn mit vectoren aussehen? Ich nehme an, dass ich dann keine Operatoren mehr Überladen muss?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wie könnte das denn mit vectoren aussehen? Ich nehme an, dass ich dann keine Operatoren mehr Überladen muss?

Doch, du musst immer noch den operator[] implementieren, weil du von std::vector nicht erben sollst.

Das könnte so aussehen:

class CMatrix
{
private:
vector<vector<double> > mat;

public:
CMatrix(int z, int s, double wert); //parametrisierter Konstruktor
CMatrix(int z, int s); //parametrisierter Konstruktor
int getLines(void) const;//gibt die Zeilenanzahl zurueck
int getCols(void) const; //gibt die Spaltenanzahl zurueck
const vector<double>& operator[] (int i) const;//prueft den Indexwert auf Gueltigkeit
vector<double>& operator[](int i);//prueft den Indexwert auf Gueltigkeit
CMatrix& operator+=(const CMatrix&);//Addition zweier Matrizen und Zuweisung
void print() const; //Bildschirmausgabe
void setWert(int z, int s, double WertTmp);//traegt Wert an bestimmte Stelle in Matrix ein
double sum(void) const; //bildet Summe der Matrix
double getWert(int z, int s) const; //gibt Wert an bestimmter Stelle in Matrix zurueck
};


CMatrix::CMatrix(int z, int s, double wert) : mat( z, vector<double>( s, wert ) )
{
}

CMatrix::CMatrix(int z, int s) : mat( z, vector<double>( s ) )
{
}

int CMatrix::getLines(void) const
{
return mat.size();
}

int CMatrix::getCols(void) const
{
return mat[0].size();
}

vector<double>& CMatrix::operator[](int i)
{
return mat.at(i);
}

const vector<double>& CMatrix::operator[](int i) const
{
return mat.at(i);
}

CMatrix& CMatrix::operator+=(const CMatrix& m)
{
if (getCols() == m.getCols() && getLines() == m.getLines() )
{
for (int i = 0; i < getLines(); ++i)
{
for (int j = 0; j < getCols(); ++j)
{
mat[i][j] += m.mat[i][j];
}
}
}
return *this;
}

void CMatrix::print() const //Bildschirmausgabe
{
for (int i = 0; i < getLines(); i++)
{
for (int j = 0; j < getCols(); ++j)
{
cout << mat[i][j] << " ";
}
cout << endl;
}
}

void CMatrix::setWert(int z, int s, double WertTmp)
{
mat[z][s] = WertTmp; //und Werte kopieren
}

double CMatrix::sum(void) const
{
double sum = 0.0; //Wert zurueck setzen

for(size_t i = 0; i < mat.size(); i++)
{
sum = accumulate( mat[i].begin(), mat[i].end(), sum );
}
return sum;
}

double CMatrix::getWert(int z, int s) const
{
return mat[z][s];
}[/code]

Für accumulate brauchst du <numeric>.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hmmm... Das ist ganz neu für mich. Hab das jetzt mal folgendermaßen implementiert:

#pragma once
#include <numeric>

class CMatrix
{
protected:
vector<vector<double> > mat;

public:
CMatrix(int z, int s, double wert); //parametrisierter Konstruktor
//CMatrix(int z, int s); //parametrisierter Konstruktor
int getLines(void) const;//gibt die Zeilenanzahl zurueck
int getCols(void) const; //gibt die Spaltenanzahl zurueck
const vector<double>& operator[] (int i) const;//prueft den Indexwert auf Gueltigkeit
vector<double>& operator[](int i);//prueft den Indexwert auf Gueltigkeit
CMatrix& operator+=(const CMatrix&);//Addition zweier Matrizen und Zuweisung
void print() const; //Bildschirmausgabe
void setWert(int z, int s, double WertTmp);//traegt Wert an bestimmte Stelle in Matrix ein
double sum(void) const; //bildet Summe der Matrix
double getWert(int z, int s) const; //gibt Wert an bestimmter Stelle in Matrix zurueck


CMatrix(void); //Konstruktor
~CMatrix(void); //Destruktor
CMatrix& operator=(const CMatrix&); //Einfache Zuweisung

};



#include "StdAfx.h"
#include ".\matrix.h"
#include <numeric>

CMatrix::CMatrix(void)
:mat(NULL)
{
}

CMatrix::~CMatrix(void)
{
}

CMatrix::CMatrix(int z, int s, double wert) : mat( z, vector<double>( s, wert ) )
{
for (int i = 0; i < getLines(); i++) //Zeilenvektoren:
{
for (int j = 0; j < getCols(); ++j)
{
mat[i][j] = wert; //und Werte kopieren
}
}
}

/*CMatrix::CMatrix(int z, int s) : mat( z, vector<double>( s ) )
{
this->lines = z;
this->cols = s;
this->mat = new vector<double>[this->lines];
for (int i = 0; i < this->lines; i++)
{
this->mat[i] = new double(this->cols);
}
}*/

int CMatrix::getLines(void) const
{
return mat.size();
}

int CMatrix::getCols(void) const
{
return mat[0].size();
}

vector<double>& CMatrix::operator[](int i)
{
return mat.at(i);
}

const vector<double>& CMatrix::operator[](int i) const
{
return mat.at(i);
}


CMatrix& CMatrix::operator=(const CMatrix& m)
{
for (int i = 0; i < getLines(); ++i) //Zeilenvektoren
{
for (int j = 0; j < getCols(); ++j)
{
mat[i][j] = m.mat[i][j]; //Werte kopieren
}
}
return *this;
}


CMatrix& CMatrix::operator+=(const CMatrix& m)
{
if (getCols() == m.getCols() && getLines() == m.getLines() )
{
for (int i = 0; i < getLines(); ++i)
{
for (int j = 0; j < getCols(); ++j)
{
mat[i][j] += m.mat[i][j];
}
}
}
return *this;
}

void CMatrix::print() const //Bildschirmausgabe
{
for (int i = 0; i < getLines(); i++)
{
for (int j = 0; j < getCols(); ++j)
{
cout << mat[i][j] << " ";
}
cout << endl;
}
}

void CMatrix::setWert(int z, int s, double WertTmp)
{
mat[z][s] = WertTmp; //und Werte kopieren
}

double CMatrix::sum(void) const
{
double sum = 0.0; //Wert zurueck setzen

for(size_t i = 0; i < mat.size(); i++)
{
sum = accumulate( mat[i].begin(), mat[i].end(), sum );
}
return sum;
}

double CMatrix::getWert(int z, int s) const
{
return mat[z][s];
}

[/PHP]

Hab es auch zum laufen gebracht, meine berechneten Werte stimmen, aber das Programm wird immernoch folgendermaßen beendet:

Das Programm "[3472] test21.exe: Systemeigen" wurde mit Code 0 (0x0) beendet.

Da ich im main mit

[PHP]int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}

arbeite, dürfte das doch nicht passieren, oder?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...