new und realloc
-
POD - keine Ahnung^^
Alignment - IMO wird der Speicher den du dir holst, auf eine gerade Bytezahl gestellt. D.h. wenn du dir 1 Byte holst (malloc/realloc/new), ist der Speicher dafür je nach System 4, 8, 16 Bytes groß oder so.
Das Problem bei deinem Code ist, dass, wenn der Speicher verkleinert wird, der Destruktor für die entfallenen Objekte nicht aufgerufen wird. Für mehr Objekte wird der Konstruktor für die neuen nicht aufgerufen. Und wenn die Objekte "verschoben" werden, weil realloc Speicher an einer anderen Stelle zurückgibt, kriegen die Objekte nix davon mit, dass sie woanders liegen, was zu Problemen führen kann.
Bei campers (abgefahrenem) Code werden size-Anzahl Objekte neu erzeugt, für die wird der Copy-Konstruktor mit Referenz auf das alte Objekt aufgerufen. Die alten werden dann dekonstrukturiert.
-
FreakyBKAs code enthält zusätzlich ein Speicherleck in:
_data = (t**) realloc (_data, size * sizeof(t*));wenn die Anforderung nicht erfüllt werden kann (realloc liefert 0 zurück). Denn der ursprüngliche Speicherblock wird dann (richtigerweise) nicht freigegeben. Der Destruktoraufruf ist kein Problem, denn es geht ja hier nur um Pointer.
-
das problem ist also, wenn realloc 0 zurückgibt hab ich keine zeiger mehr auf die objekte?
-
FreakyBKA schrieb:
das problem ist also, wenn realloc 0 zurückgibt hab ich keine zeiger mehr auf die objekte?
exakt.
-
FreakyBKA schrieb:
das problem ist also, wenn realloc 0 zurückgibt hab ich keine zeiger mehr auf die objekte?
exakt. Die Funktion sollte am besten nichts verändern, wenn sie nicht in der Lage ist, ihre Funktion auszuführen. Du veränderst aber den member _data bevor du weißt, ob nicht eine exception geworfen werden muss.
-
also wäre folgendes besser:
template <class t> inline void carray<t>::set_size(int size) { if (size == _size) return; try { t** tmp = (t**) realloc (_data, size * sizeof(t*)); if (size && !tmp) throw memory_exception(0); _data = tmp; for(int i = size; i < _size; i++) { delete _data[i]; _data[i] = 0; }; for(int i = _size; i < size; i++) _data[i] = 0; _upper_bound = min(size - 1, _upper_bound); _size = size; } catch(cexception e) { cout << e; }; };
-
FreakyBKA schrieb:
also wäre folgendes besser:
template <class t> inline void carray<t>::set_size(int size) { if (size == _size) return; try { t** tmp = (t**) realloc (_data, size * sizeof(t*)); if (size && !tmp) throw memory_exception(0); _data = tmp; for(int i = size; i < _size; i++) { delete _data[i]; _data[i] = 0; }; for(int i = _size; i < size; i++) _data[i] = 0; _upper_bound = min(size - 1, _upper_bound); _size = size; } catch(cexception e) { cout << e; }; };schon. wie kommst du eigentlich auf die Idee, per delete _data[i] daten zu löschen, wenn du schon realloc aufgerufen hast und _data[i] außerhalb deines Datenblocks liegt ?
Das mußt du vorher machen. Glücklicherweise schlägt realloc niemals fehl, wenn die angeforderte Größe nicht größer als der bereitsvorliegende Datenblock ist - du hast hier also kein Problem.
-
stimmt, hab ich übersehen werde ich gleich mal ändern.
-
was mache ich denn wenn ich einen typ der form
int[2], char*oder so habe, also quasi wieder dynamischer speicher.
der muss ja auch wieder ordnungsgemäß freigegeben werden.
-
Nein. Du musst nur Speicher wieder freigeben, den du mit new oder malloc angefordert hast.