speicherallokierung und -freigabe...
-
template <class T> void array<T>::set_dim(unsigned int zeilen) { delete [] array_eindim; // Alles was vorher war löschen array_eindim = new T[zeilen]; zeilen_array = zeilen; index_z = 0; }das habe ich mal probiert, und ich bekomme folgendes wenn ich mein programm starte:
/bin/sh: line 1: 13181 Speicherzugriffsfehler ./perzeptron Betätigen Sie die Eingabetaste, um fortzufahren!wenn ich
delete [] array_eindim;weglasse, funktioniert es aber wieder:
Position 0: 0.1 ist 0 Betätigen Sie die Eingabetaste, um fortzufahren!allerdings habe ich wahrscheinlich durch diesen memory leak einen fehler wenn ich best. funktionen die set_dim() aufrufen mehrmals benutze...
-
Poste doch mal deine Header-Datei mit der Klassendefinition
-
diese basisklasse verwende ich! soll ein "etwas" dynamisches array-handling ermöglichen...
#ifndef ARRAY_KLASSE #define ARRAY_KLASSE #include <iostream> #include <cstdlib> template <class T> class array { private: T *array_eindim; unsigned int zeilen_array; unsigned int index_z; public: array(); array(unsigned int z); array(array<T> const& ref); ~array(); T *get_array(); T get_element(unsigned int zeile); //unsigned int get_zeilen(); //sinnlos void ausgabe_array(); void set_dim(unsigned int z); void push_back(T data);//zu machen void push_back(T *feld, unsigned int zeilen_feld); void push_pos(T *feld, unsigned int zeilen_feld, int pos_z); T mult(T *feld, unsigned int zeilen_feld); void clear_all(); }; //############################################################################## template <class T> inline array<T>::array() : index_z(0), zeilen_array(0) {} template <class T> inline array<T>::array(unsigned int zeilen) : index_z(0), zeilen_array(zeilen) { array_eindim = new T[zeilen]; } template <class T> inline array<T>::array(array<T> const& ref) : index_z(ref.index_z), zeilen_array(ref.zeilen_array) { array_eindim = new T[zeilen_array]; for(int i = 0; i < zeilen_array; ++i) array_eindim[i] = ref.array_eindim[i]; } template <class T> array<T>::~array() { delete [] array_eindim; } template <class T> T *array<T>::get_array() { return array_eindim; } template <class T> T array<T>::get_element(unsigned int z) { if(z < zeilen_array) return array_eindim[z]; } /* template <class T> unsigned int array<T>::get_zeilen() { return zeilen_array; } */ template <class T> void array<T>::set_dim(unsigned int zeilen) { //delete [] array_eindim; array_eindim = new T[zeilen]; zeilen_array = zeilen; index_z = 0; } template <class T> void array<T>::ausgabe_array() { for(unsigned int i = 0; i < zeilen_array; i++) std::cout << "Position " << i << ": " << array_eindim[i] << std::endl; if(zeilen_array == 0) std::cout << "Array leer!" << std::endl; } template <class T> void array<T>::push_back(T data) { array_eindim[index_z] = data; index_z++; } template <class T> void array<T>::push_back(T *feld, unsigned int feld_zeilen) { for(unsigned int i = 0; i < feld_zeilen; ++i && ++index_z) array_eindim[index_z] = feld[i]; } template <class T> void array<T>::push_pos(T *feld, unsigned int feld_zeilen, int position_zeile) { for(unsigned int i = position_zeile, j = 0; i < (feld_zeilen + position_zeile); i++, j++) array_eindim[i] = feld[j]; if( (feld_zeilen + position_zeile) > index_z) index_z = (feld_zeilen + position_zeile); } template <class T> T array<T>::mult(T *feld, unsigned int zeilen_feld) { T temp; for(unsigned int i = 0; i < zeilen_array && i < zeilen_feld; i++) temp = array_eindim[i] * feld[i]; return temp; } template <class T> void array<T>::clear_all() { for(unsigned int i = zeilen_array; i < zeilen_array; i++) array_eindim[i] = 0; index_z = 0; } #endifanwenden tue ich dass im moment hier:
#include <iostream> #include <cstdlib> #include "array.hpp" #include "matrix.hpp" class perzeptron { private: array<float> eschicht; array<float> aschicht; array<float> ea_schicht; float schwelle; public: perzeptron(int eing, int ausg); array<float> durchlauf(float *data); void training(); void set_zurueck(); }; void fill_array(array<float> &array, int grenze) { /* for(int i = 0; i < grenze; i++) array.push_back(1); */ array.push_back(0.1); array.push_back(0.3); } perzeptron::perzeptron(int eing, int ausg) { schwelle = 0.5; eschicht.set_dim(eing); //hier 2 aschicht.set_dim(ausg); //hier 1 ea_schicht.set_dim(eing); fill_array(ea_schicht, 2); //mit '1' gefüllt } array<float> perzeptron::durchlauf(float daten[2]) { eschicht.push_back(daten, 2); aschicht.push_back( ea_schicht.get_element(0)*eschicht.get_element(0) + ea_schicht.get_element(1)*eschicht.get_element(1) ); aschicht.ausgabe_array(); if(aschicht.get_element(0) > schwelle) std::cout<<"ist 1"<<std::endl; else std::cout<<"ist 0"<<std::endl; return aschicht; }wenn ich in der main dass mache kriege ich speiicherzugriffsfehler
float data1[2] = {0,0}; float data2[2] = {0,1}; float data3[2] = {1,0}; float data4[2] = {1,1}; perzeptron perz(2, 1); perz.durchlauf(data1); perz.durchlauf(data2); perz.durchlauf(data3); perz.durchlauf(data4);wenn ich aber nur
perz.durchlauf(data1);das mache hab ich noch keinen fehler, ich glaub das liegt an der set_dim()-fkt.
-
setz "array_eindim" in dem Konstruktor, wo du nichts machst mal auf NULL und überprüfe vor jedem delete, ob überhaupt ein Array angelegt wurde!!!
-
Ich würde mir auch push_back nochmal genauer ansehen. Du testst da nicht auf Überlauf (index_z > zeilen_array).
-
mir fehlt programmierübung, ich mach sowas eigentlich nur wenn ich lust habe, im moment müssten alle fehler behoben sein! noch irgendwelche ratschläge, fehler, verbesserungen, etc.

#ifndef ARRAY_KLASSE #define ARRAY_KLASSE #include <iostream> #include <cstdlib> template <class T> class array { private: T *array_eindim; unsigned int zeilen_array; unsigned int index_z; public: array(); array(unsigned int z); array(array<T> const& ref); ~array(); T *get_array(); T get_element(unsigned int zeile); //unsigned int get_zeilen(); //sinnlos void ausgabe_array(); void set_dim(unsigned int z); void push_back(T data);//zu machen void push_back(T *feld, unsigned int zeilen_feld); void push_pos(T *feld, unsigned int zeilen_feld, int pos_z); T mult(T *feld, unsigned int zeilen_feld); void clear_all(); }; //############################################################################## template <class T> inline array<T>::array() : index_z(0), zeilen_array(0) { array_eindim = NULL; } template <class T> inline array<T>::array(unsigned int zeilen) : index_z(0), zeilen_array(zeilen) { array_eindim = new T[zeilen]; } template <class T> inline array<T>::array(array<T> const& ref) : index_z(ref.index_z), zeilen_array(ref.zeilen_array) { array_eindim = new T[zeilen_array]; for(int i = 0; i < zeilen_array; ++i) array_eindim[i] = ref.array_eindim[i]; } template <class T> array<T>::~array() { if(array_eindim != NULL) delete [] array_eindim; } template <class T> T *array<T>::get_array() { return array_eindim; } template <class T> T array<T>::get_element(unsigned int z) { if(z < zeilen_array) return array_eindim[z]; } /* template <class T> unsigned int array<T>::get_zeilen() { return zeilen_array; } */ template <class T> void array<T>::set_dim(unsigned int zeilen) { if(array_eindim != NULL) delete [] array_eindim; array_eindim = new T[zeilen]; zeilen_array = zeilen; index_z = 0; } template <class T> void array<T>::ausgabe_array() { for(unsigned int i = 0; i < zeilen_array; i++) std::cout << "Position " << i << ": " << array_eindim[i] << std::endl; if(zeilen_array == 0) std::cout << "Array leer!" << std::endl; } template <class T> void array<T>::push_back(T data) { array_eindim[index_z] = data; if(index_z <= zeilen_array) index_z++; } template <class T> void array<T>::push_back(T *feld, unsigned int feld_zeilen) { for(unsigned int i = 0; i < feld_zeilen && index_z <= zeilen_array; ++i && ++index_z) array_eindim[index_z] = feld[i]; } template <class T> void array<T>::push_pos(T *feld, unsigned int feld_zeilen, int position_zeile) { for(unsigned int i = position_zeile, j = 0; i < (feld_zeilen + position_zeile); i++, j++) array_eindim[i] = feld[j]; if( (feld_zeilen + position_zeile) > index_z) index_z = (feld_zeilen + position_zeile); } template <class T> T array<T>::mult(T *feld, unsigned int zeilen_feld) { T temp; for(unsigned int i = 0; i < zeilen_array && i < zeilen_feld; i++) temp = array_eindim[i] * feld[i]; return temp; } template <class T> void array<T>::clear_all() { for(unsigned int i = zeilen_array; i < zeilen_array; i++) array_eindim[i] = 0; index_z = 0; } #endif
-
Ich würde in deinem Fall auf das push_back lieber ganz verzichten, da es unter Umständen nicht das macht was man von ihm erwartet (übrigens dort < (zeilen_array-1)und nicht <=).
Überlade lieber operator[] oder erzeugen eine Memberfunktion wie at(). Da kann man auch eine Indexüberprüfung machen.
Statt push_back mit T* könnte man einen spezialisierten Konstruktor verwenden.
oder verwende gleich vector oder boost::array.
-
was meinst du mit "nicht das machen, was man erwartet"?
-
Ein push_back, z.Bsp. eines vector, hängt Elemente an das Ende deines Vectors an und allokiert bei Bedarf auch neuen Speicher (und kopiert dann). Wenn bei dir das Ende deines Arrays erreicht ist würde das letzte Element überschrieben.
Das meine ich damit.
-
achso, das wird bald weggecodet
, ich überleg nur wie man das ohne umkopieren machen kann!!!
-
exigoner schrieb:
noch irgendwelche ratschläge, fehler, verbesserungen, etc.

Lass die Überprüfung auf NULL vor delete weg, das ist Unsinn. Und lies dir meinen ersten Beitrag noch mal durch.

-
exigoner schrieb:
noch irgendwelche ratschläge, fehler, verbesserungen, etc.
Lass die Überprüfung auf NULL vor delete weg, das ist Unsinn. Und lies dir meinen ersten Beitrag noch mal durch.

Was soll der erste Tip bringen?
In seiner Klasse gibt es doch nun beide Möglichkeiten, dass das Feld erstellt wurde oder halt nicht. Warum soll er da einfach die Überprüfung weglassen? Würde im letzter Fall ja die schon erwähnte Fehlermeldung bringen.
-
Würde es nicht.
Ein delete auf einen Nullpointer gibt keine Exception.
-
gut ok, aber hier is ein delete auf ein Feld, also []delete, und da bringt er zumindest bei mir auch bei nem NULL-Pointer ne Exception
-
cppLer schrieb:
gut ok, aber hier is ein delete auf ein Feld, also []delete, und da bringt er zumindest bei mir auch bei nem NULL-Pointer ne Exception
Blöd wenn sich was nicht an den Standard hält oder?
-
cppLer schrieb:
gut ok, aber hier is ein delete auf ein Feld, also []delete, und da bringt er zumindest bei mir auch bei nem NULL-Pointer ne Exception
Kann ich mit dem gcc 3.4 nicht bestaetigen.
-
cppLer schrieb:
Was soll der erste Tip bringen?
delete kann nicht fehlschlagen, new aber schon. Und wenn geanu dieser Fall in set_dim eintritt, ist sein Objekt "kaputt".
cppLer schrieb:
In seiner Klasse gibt es doch nun beide Möglichkeiten, dass das Feld erstellt wurde oder halt nicht. Warum soll er da einfach die Überprüfung weglassen? Würde im letzter Fall ja die schon erwähnte Fehlermeldung bringen.
Ich darf für dich mal den Standard zitieren
ISO/IEC 14882:2003(E) schrieb:
if the value of the operand of delete is the null pointer the operation has no effect
(5.3.5-2)
-
mmh, also lass ich die überprüfung weg, früher kam, da immer ne komische fehlermeldung...
jetz aber nicht mehr! trotzdem ist die überprüfung best. performance-verbessernd, oder?
-
exigoner schrieb:
mmh, also lass ich die überprüfung weg, früher kam, da immer ne komische fehlermeldung...
jetz aber nicht mehr! trotzdem ist die überprüfung best. performance-verbessernd, oder?Ich vermute, dass der delete-Operator eine solche Ueberpruefung einfach selber macht. Schliesslich hat er bei einem NULL-Pointer nichts zu tun. Wenn man diese nochmal darum setzt, wird der Compiler - mit etwas Glueck - diese Abfrage weg-optimieren.
-
if the value of the operand of delete is the null pointer the operation has no effect
bezieht sich das auch wirklich auf []delete ???
steht ja nur ohne Klammern da ... .