realloc liefert zu viel speicher
-
folgendes:
char* string = 0; //... string = (char*) realloc (string, (get_upper_bound() + 1) * sizeof(char));wobei get_upper_bound() den Wert 8 zurückliefert und string vorher 0 ist.
nach der realloc anweisung sieht string wie folgt ausstring = "ÍÍÍÍÍÍÍÍÍýýýý««««««««þîþ"hat also viel zu viel speicherplatz bekommen, aber ich weiß nicht warum. vllt hat ja jemand ne ahnung woran es liegen könnte, danke schon mal im voraus.
-
- ist das eher ein C problem und kein C++ problem. in C++ verwendest du new.
- was erwartest du das in dem string drinnen steht ? wenn du 8 bytes allokierst, bedeutet das das du nur die 8 bytes verwenden darfst, da du sonst in fremden oder nicht allokierten speicher reinschreibst.
Meep Meep
-
FreakyBKA schrieb:
nach der realloc anweisung sieht string wie folgt aus
string = "ÍÍÍÍÍÍÍÍÍýýýý««««««««þîþ"hat also viel zu viel speicherplatz bekommen, aber ich weiß nicht warum. vllt hat ja jemand ne ahnung woran es liegen könnte, danke schon mal im voraus.
Du interpretierst die Ausgabe vollkommen falsch. Tatsächlich hast Du nur die ersten 9 Bytes allokiert und darfst auch nur diese Benutzen. Alles danach wären unerlauvter Speicherzugriff.
Aber... Ein String in C ist definiert als eine mit 0 terminierte Zeichenkette. Da der allokierte Speicher nicht automatisch auf 0 gesetzt wird, wird im Prinzip alles bis zur ersten zufälligen 0 im Speicher als String interpretiert.
Auch ist der String nicht vorher 0, sondern der Zeiger auf String ist 0. Solange der Zeiger 0 ist hat er naturgemäß auch keinen Inhalt... Durch realloc setzt du den Zeiger auf die Anfangsadresse des neu reservierten Speichers, mehr nicht... Der Inhalt dieses Speichers ist rein zufällig.
-
Diese Ìs sind wahrscheinlich das Zeichen das zu dem Bit-pattern gehört mit welchem dein Compiler nicht initialisierten Speicher im Debug-Build kennzeichnet.
Alles danach ist fremder Speicher.
-
also allokiere ich einfach 1 speicherplatz mehr und setze die letzte stelle auf '\0' und dann sollte es funktionieren?
-
FreakyBKA schrieb:
also allokiere ich einfach 1 speicherplatz mehr und setze die letzte stelle auf '\0' und dann sollte es funktionieren?
Nein, falsch. Sondern Du verwendest 'std::string'.
-
FreakyBKA schrieb:
also allokiere ich einfach 1 speicherplatz mehr und setze die letzte stelle auf '\0' und dann sollte es funktionieren?
ja. Es ist kein C-String wenn keine 0 am Ende ist! Aber ich würde dir auch eher zu std::string raten.
Ansonsten:
1. sizeof(char) ist immer 1
2. malloc/realloc/calloc/free benutzt man in C++ nicht mehr. Dafür benutzt man jetzt new
-
warum soll das falsch sein? das ist alles im rahmen einer eigenen string klasse, aber auch egal, es funktioniert jetzt.
-
FreakyBKA schrieb:
warum soll das falsch sein? das ist alles im rahmen einer eigenen string klasse
Dann kannst du 'eh die C-String Repräsentation für die Datenspeicherung verwerfen. Ein simples Array tut es da genauso und ist effizienter. Und *alloc/free solltest du trotzdem durch new/delete ersetzen.
-
aber wenn ich new/delete verwende dann kann ich nicht mehr nachträglich den speicher vergrößern und muss jedesmal neues feld erstellen und kopieren. was genau ist denn gegen malloc/realloc/free einzuwenden?
-
malloc() und Co. arbeiten wunderbar - mit PoD-Typen. Aber sie haben keine Ahnung von Konstruktoren und dergleichen.
(und intern dürfte realloc auch nicht viel anders machen als einen neuen Speicherblock abzufordern und die Daten dort reinzukopieren - nur eventuell auf HW-Ebene besser optimiert)
-
also in einen anderen Thread, wurde mir mal gesagt das realloc ersteinmal versucht den aktuellen speicher zu vergrößern und andernfalls neu allokiert. andere frage was sind denn PoD-Typen?
-
FreakyBKA schrieb:
also in einen anderen Thread, wurde mir mal gesagt das realloc ersteinmal versucht den aktuellen speicher zu vergrößern und andernfalls neu allokiert.
Korrekt. Und wenn man komplexe Speicheranforderung in C++ braucht, kann man Allokatoren verwenden.
andere frage was sind denn PoD-Typen?
Plain old data. Alles, was keine Klasse ist.
-
Naja, das kommt darauf an was man unter einer Klasse versteht...
class Foo { public: int x; void sepp() { x++; } };-> Foo ist ein POD.
Die genauen Regeln weiss ich aber auch nimmer, müsste ich selbst nachgucken.
-
hustbaer schrieb:
Die genauen Regeln weiss ich aber auch nimmer, müsste ich selbst nachgucken.
Kurzfassung: POD ist alles, was du auch als C-struct übergeben kannst. Ausführlicher: Keine Konstruktoren oder Destruktoren, keine Ableitung, keine virtuellen Methoden, keine privaten Elemente. (und natürlich müssen alle Member ebenfalls POD's oder built-in Typen sein)
-
Danke. z.B. bei Konstruktoren und non-public Members war ich mir nicht sicher -- würde ja eigentlich nicht stören.
Andere Frage... ist das noch ein POD:class foo { public: int x; public: int y; };?
Weil ja x und y im Speicher nicht so hintereinander liegen müssen (kann auch erst y und dann x kommen) soweit ich den Standard kenne/verstehe.
Geht das nun trotzdem noch als POD durch?
-
hustbaer schrieb:
Danke. z.B. bei Konstruktoren und non-public Members war ich mir nicht sicher -- würde ja eigentlich nicht stören.
Huh? Na gerade der Konstruktor macht doch einen riesigen Unterschied. Angenommen, man deklariert ein Feld von Objekten mit 1000 Einträgen. Wenn es sich um Non-PODs handelt, dann müssen 1000 Konstruktoren aufgerufen werden. Das kann für ganz erhebliche Performance-Unterschiede sorgen. Non-public-Members stören in der Tat nicht.
-
hustbaer schrieb:
Danke. z.B. bei Konstruktoren und non-public Members war ich mir nicht sicher -- würde ja eigentlich nicht stören.
Andere Frage... ist das noch ein POD:class foo { public: int x; public: int y; };?
Weil ja x und y im Speicher nicht so hintereinander liegen müssen (kann auch erst y und dann x kommen) soweit ich den Standard kenne/verstehe.
Geht das nun trotzdem noch als POD durch?Ist immer noch ein POD. Die Umordnungsregel trifft PODs nicht, denn man könnte immer einen layout-kompatiblen Typen konstruieren, der ohne zusätzliche Zugriffsspezifikation auskommt.
Konstruktoren (&Destruktoren) sind im Prinzip der wichtigste Faktor, der zu nicht-PODs führt: ohne Konstruktor haben wir nur eine Anhäufung von Daten ohne inneren Zusammenhang - mithin auch keinerlei Invarianten, die während der Lebenszeit gelten könnten. Konstruktoren machen es erst möglich, dass aus einer bloßen Aggregation ein größeres Ganzes wird.
-
ZU dem Thema ne Frage, die mich schon länger beschäftigt: Warum gibt es kein C++-Equivalent zu realloc(). malloc() <-> new und free() <->delet ist ja klar, aber realloc()? Immerhin würde man doch vielleicht mal ein Feld vergrößern wollen.
-
geloescht schrieb:
ZU dem Thema ne Frage, die mich schon länger beschäftigt: Warum gibt es kein C++-Equivalent zu realloc(). malloc() <-> new und free() <->delet ist ja klar, aber realloc()? Immerhin würde man doch vielleicht mal ein Feld vergrößern wollen.
Weil C++ keine Abbildung von C mit neuen Worten ist. Für sich vergrößern wollende Felder gibt es so schöne Sachen wie std::vector<T>, die unter der Haube mit Allokatoren arbeiten die ähnliches wie realloc leisten dürften.
-
LordJaxom schrieb:
Weil C++ keine Abbildung von C mit neuen Worten ist. Für sich vergrößern wollende Felder gibt es so schöne Sachen wie std::vector<T>, die unter der Haube mit Allokatoren arbeiten die ähnliches wie realloc leisten dürften.
Der standardmäßig verwendete Allokator dürfte wohl auch bloß new und delete benutzen (ist bei mir mit g++ 4.1.2 so). Besitzt eine normale Allokatorklasse überhaupt die Fähigkeit des Vergrößern bzw. Verkleinerns des Speicherbereichs? Und selbst wenn, es werden sich so keine system- und compilerunabhängige Allokatoren mit dieser Fähigkeit schreiben lassen: Die müssten entweder auf Betriebssystemfunktionen oder auf realloc() + manuelles Aufrufen des Konstruktors zurückgreifen. Hab Allokatoren noch nie benutzt, also lasse ich mich gerne eines Besseren belehren. <nicht ganz ernst gemeinte ironie> Schön, dass wir nochmal eine Abstraktionsschicht für die Speicherverwaltung haben, damit können wir jetzt unsere Abstraktionsschicht für die Abstraktion der Abstraktion abstrahieren ;)</ironie>