wie weiss delete[] array die Array Grösse
-
Andromeda schrieb:
Aber manche lieben sowas ja.

Das glaube ich nicht. Es gibt welche, die haben keine Ahnung von sowas und deswegen ist es denen egal (aber sie bevorzugen dann diesen Stil, ja). Aber es gibt auch viele Fälle, da kommst nicht drumherum. Allein schon type erasure wie bei std::function oder tausende andere Fälle, wo man das einfach braucht oder die Alternativen andere Nachteile haben.
-
@happystudent
Wenn das Array aus Elementen besteht deren Destruktor nicht trivial ist, dann muss die exakte Grösse irgendwo gespeichert sein. Sonst wüsste die Implementierung ja nicht wie viele Objekte beidelete[]zerstört werden müssen bevor der Speicher freigegeben werden kann.
Man könnte den Support für "Grösse Abfragen" auch einfach auf solche Arrays beschränken.ps: Es gibt nämlich Allokatoren die Pools für kleine Allokationen verwenden, wo mehr als nur ein wenig aufgerundet werden muss. Also angenommen 160 Byte werden für 10 Objekte a 16 Byte angefordert, aber der kleinste passende Pool verwaltet 180 Byte Blöcke. Das wären dann 11 Objekte wenn man zurückrechnet. Bei Arrays aus Objekten mit trivialem Destruktor wäre das egal, es muss ja nur der Speicher freigegeben werden. Und das kann der Allokator, ohne dass er sich irgendwo pro Block merkt wie gross dieser war, so lange der Block aus einem seiner fixgrösse Pools stammt. (Man kann das so implementieren dass man anhand der Adresse feststellen kann aus welchem Pool ein Block kommt. Und damit kennt man dann die Grösse des Pool-Blocks, also die 180 Byte. Nicht aber die 160.)
Wenn der Destruktor aber aufgerufen werden muss, dann muss die Implementierung halt doch wissen dass es bloss 10 Objekte sind.
D.h. wenn die Implementierung nicht an einen Allokator gebunden ist (=mit beliebigen Allokatoren klar kommen will/muss), dann muss sie - egal was der Allokator macht - die Grösse in diesem non-trivial-dtor Fall selbst nochmal irgendwo abspeichern.Im Worst Case wären wird dann bei drei Kopien der Grösse:
1x im bzw. für den Allokator selbst
1x irgendwo für die C++ Implementierung
1x im eigenen ProgrammSogesehen halte ich es schon für eine "ungünstige" Entscheidung dass man die Array-Grösse grundsätzlich nicht abfragen kann. Grundsätzlich immer wäre vermutlich auch verkehrt, weil man dadurch bei Allokatoren wie oben beschrieben und trivial-dtor Objekten wieder eine u.U. unnötige Kopie der Grösse erzwingen würde.
-
Vielen Dank für die angeregte Diskussion, da wurden für mich sehr interessante Punkte angesprochen.
Ich fasse das für mich dann, der Einfachheit zuliebe, so zusammen:
für die C oder C++ runtime ist die Größen-Infromation zwar da,
man hat aber entschieden diese nicht zugänglich zu machen,
oder darauf vergessen und das nie repariert,
zumindest bei den Array Typen wo die Information sowieso verfügbar ist,
es aber möglich ist das reservierter Bereich größer ist als vom User angefordert und im dem Fall der User wissen/-buchhalten muss wo sein letztes gültiges Element ist.
Wobei, wenn ich Platz für 10 anfordre, und aus Gründern der Optimierung Platz für 11 zurückbekommen sollte, dann sollte man mir dies Information doch auch nicht vorenthalten?Nunja, warum repariert man das eigentlich in den ganzen Standard Komitee Sitzungen nicht, zu trivial?
-
kurze_frage schrieb:
Nunja, warum repariert man das eigentlich in den ganzen Standard Komitee Sitzungen nicht, zu trivial?
welchen zweck hätte das denn? und was würde passieren wenn
int x[]=new int[256]; delete[23] x;
-
HansKlaus schrieb:
... delete[23] x;Bittewas?
kurze_frage: Die Größe eines Arrays ermittelst du mit sizeof(arr)/sizeof(T).
-
Den Mist oben ignorieren, hier gehts ja um Speicherreservierung

-
@HansKlaus
Es gäbe ja mehrere Arten wie man es reparieren kann.
WENN man die Variante wählt dass man bei delete[] selbst mitgeben muss wie viele Elemente es gibt (was mMn. nicht die beste Variante ist), dann würde in deinem Beispiel das selbe passieren wie z.B. beichar* p = new char[123]; delete p; delete p; // undefined behavioroder auch
char* p = new char[123]; p++; delete p; // undefined behavior
-
HansKlaus schrieb:
kurze_frage schrieb:
Nunja, warum repariert man das eigentlich in den ganzen Standard Komitee Sitzungen nicht, zu trivial?
welchen zweck hätte das denn? und was würde passieren wenn
int x[]=new int[256]; delete[23] x;nein, natürlich nicht
tippender schrieb:
kurze_frage: Die Größe eines Arrays ermittelst du mit sizeof(arr)/sizeof(T).
also ich mach das nicht so gerne mit dynamischen arrays (welche ich sowieso nicht verwende wenn ich nicht muss)
char* p = new char[123] ; std::cout << sizeof(p)/sizeof(char) ;das ist nicht die Größe eines Arrays
brauchbar wäre doch eher
char* p = new char[123] ; arraySize(p) ; // 123 arraySize(++p) ; // ?? oder eventuell 0wenn delete[] (p) die grösse weiß,
warum nicht eine arraySize(p) Methode die es mir verrät?es ist doch nicht konsequent, symmetrisch, schön und nützlich eine solche Funktion nicht zu haben.
Denk ich mir halt, ich und wollte wissen ob es fundierte Gründe gibt das uns diese Funktion, eventuell mit einem anderen Namen, vorenthalten wird.
-
Nunja, warum repariert man das eigentlich in den ganzen Standard Komitee Sitzungen nicht, zu trivial?
ballast aus alten tagen, den man nicht so einfach über bord werfen kann, ohne vielen leuten das leben schwer und die brieftasche leicht zu machen.
da erfindet man lieber neue konstrukte und wartet zunächst ein paar (zehn oder mehr) jahre, bevor man die alten aufgibt. (z.b. char*x="lit" vs const char*x="lit"), und das ist auch gut so.in der zwischenzeit sollte man eben, so gut es geht, auf manuelle dynamische speicherverwaltung verzichten. std::vector z.b. bietet alles, was man braucht:
std::vector<char> array; array.reserve(42); array.resize(23); array.size(); array.capacity();
-
HansKlaus schrieb:
welchen zweck hätte das denn? und was würde passieren wenn
[code]
int x[]=new int[256];
delete[23] x;Es hätte den Zweck / Vorteil, dass der, der sich die Länge selber speichert, oder bei dem die Länge eine Konstante ist, nicht für den overhead zahlen muss.
Wenn die falsche Länge beim Freigeben angegeben wird, dann würde das C++-übliche "undefined behaviour" zuschlagen.
Dynamisch erzeugte arrays ist doch so ein spezial-Fall, den doch kaum noch jemand nutzt.
-
welchen overhead? irgendwo muss doch sowieso gespeichert werden, wie groß das array ist, weil das betriebssystem sonst gar nicht weiß, wie viel speicher es noch zur verfügung hat.
c++-übliches undefined behaviour? also ich weiß, dass die cpu "mal eben so" einen neustart durchführt, wenn sie nicht-definierte zustände feststellt, weil so etwas den supergau schlechthin darstellt.
aber eigentlich wird mit delete nur ein tabelleneintrag in der form "anfangsadresse, endadresse" gelöscht, von daher gibt es da auch keine fehlermöglichkeit.dynamische arrays werden schon benutzt, bei typischen anwendungsfällen von c++ allerdings eher unsichtbar für den benutzer.
-
HansKlaus schrieb:
welchen overhead? irgendwo muss doch sowieso gespeichert werden, wie groß das array ist, weil das betriebssystem sonst gar nicht weiß, wie viel speicher es noch zur verfügung hat.
Das Betriebssystem hat in der Regel überhaupt nichts mit dem Allocator aus der C++ Runtime Library zu tun (ausser das sich der Allocator dort Speicher holt). Und der Allocator muss sich nicht merken, wie groß ein dynamisch alloziiertes Array ist, wenn er die Informationen beim Freigeben wieder mit bekommt.
Wenn der Allocator gezwungen wird, diese Informationen zu speichern, dann sind diese Informationen zwangsläufig nur noch zur Laufzeit bekannt. Jede Optimierung, die möglich wäre, weil die Informationen bereits zur compile-Zeit bekannt sind, werden damit unmöglich.
HansKlaus schrieb:
c++-übliches undefined behaviour? also ich weiß, dass die cpu "mal eben so" einen neustart durchführt, wenn sie nicht-definierte zustände feststellt, weil so etwas den supergau schlechthin darstellt.
"undefined behaviour" ist ein stehender Begriff in der C++-Welt. Das ist unbedingt zu vermeiden und es hat sich auch keiner die Mühe gemacht, zu definieren, was in solchen Situationen zu passieren hat. double delete ist z.B. auch so ein Fall. Bei einer "üblichen" Implementierung eines heaps, wir ein frei gewordenes Stück Speicher einfach in eine Liste freier Speicher mit einer bestimmten Größe gehängt. Ein double delete führt in dem Fall dann einfach dazu, dass der gleiche Speicher zwei mal in der Liste hängt.
HansKlaus schrieb:
aber eigentlich wird mit delete nur ein tabelleneintrag in der form "anfangsadresse, endadresse" gelöscht, von daher gibt es da auch keine fehlermöglichkeit.
Wer diese Informationen von der C++ Runtime haben möchte, kann doch einfach std::vector verwenden.