realloc
-
Hi - ich habe eine Klasse, die ich zum Verwalten von mehreren Pizzen etc. - ich habe mir einfach 3 structs gemacht und die dann ineinander verschachtelt speichern alles wichtige und damit sie nicht so allein sind, hab ich sie einfach ma in ne klasse gepackt ^^
Aber macht euch doch selbst ein Bild - hier der Code:
//die structs an sich struct pizza_item { unsigned __int32 handle; //ein handle zum identifizieren char *name; //Anzeigename char *beschreibung; //Beschreibung dazu float *preis; //preise (n (eigtl 0<n<4, aber sollte ja theoretisch für unendlich viele ausgelegt sein) Preise für verschiedene Größe) }; struct pizza_list //die Pizzen sind in Listen unterteilt { unsigned __int16 id; //id zur Liste char *name; //Name der Liste char **beschreibung; //n Überschriften für versch. Größen (22cm; 26cm; ...) unsigned __int8 ppi; //Anazhl der Preise pro Pizza signed __int16 itemcount; //Anazhl der Pizzen in dieser Liste pizza_item *items; //Array der Items }; struct pizza_main //als zusammenfassung der listen { signed __int32 listcount; //Anz. der Listen pizza_list *lists; //Array der Listen };class pizza { /*...*/ private: //Funktionen void additem (unsigned __int16 ListNr, unsigned __int32 Handle, char *Name, char *Beschreibung, float *Preise); void addlist (unsigned __int16 ID, char *Name, char **Beschreibungen, unsigned __int8 PpI); void newmain (); /*public: konstruktor / destruktor / ...*/ };//Konstruktors mit zu nächst statischer Zuweisung /*...*/ char **b = (char **) malloc (3 * sizeof(char*)); b[0] = new char; strcpy (b[0], "eins"); b[1] = new char; strcpy (b[1], "zwei"); b[2] = new char; strcpy (b[2], "drei"); this->addlist (1, "Liste+Nr.+1", b, 2);//neue Liste erstellen free (b); /*...*/ float p[2] = {4.5, 6.5}; this->additem (1, ++handle, "Pizza+Nr.+1", "Beschreibung+der+Pizza+Nr.+1", p); /*...*/Jetzt das Stück mit Fehler:

//die Funktion mal komplett, weil ich mir den Fehler nicht erklären kann void pizza::additem (unsigned __int16 ListNr, unsigned __int32 Handle, char *Name, char *Beschreibung, float *Preise) { this->Main->lists[ListNr].items = (pizza_item *) realloc (this->Main->lists[ListNr].items, (size_t) (++this->Main->lists[ListNr].itemcount * sizeof (pizza_item))); //gibt manchmal NULL zurück (und der Debugger schreibt mir, dass der erste Zugriffsfehler stattgefunden hätte) - aber es scheint so, als ob das nur bei längeren Beschreibungen so wäre //wenn ich die Reihenfolge ändere (strcpy (beschreibung, ...) direkt nach dem strcpy vom Namen, dann gibt es in der for-schleife für die Preise Zugriffs-Fehler this->Main->lists[ListNr].items[this->Main->lists[ListNr].itemcount-1].handle = Handle; this->Main->lists[ListNr].items[this->Main->lists[ListNr].itemcount-1].name = new char; strcpy (this->Main->lists[ListNr].items[this->Main->lists[ListNr].itemcount-1].name, Name), this->Main->lists[ListNr].items[this->Main->lists[ListNr].itemcount-1].preis = (float *) malloc ((size_t) (this->Main->lists[ListNr].ppi * sizeof (float))); for (unsigned __int8 i = 0; i < this->Main->lists[ListNr].ppi; i++) { this->Main->lists[ListNr].items[this->Main->lists[ListNr].itemcount-1].preis[i] = Preise[i]; } this->Main->lists[ListNr].items[this->Main->lists[ListNr].itemcount-1].beschreibung = new char; strcpy (this->Main->lists[ListNr].items[this->Main->lists[ListNr].itemcount-1].beschreibung, Beschreibung); }Danke schon mal!!!
unskilled
//edit: Nur paar Fehler weggemacht, die beim Ab- und Umschreiben enstanden sind ^^
-
hmm.. willst du C oder C++ programmieren?
wenn du schon Klassen verwendest, und OOP verstanden hast, dann nimm "new" und "delete" und lassen den "realloc, malloc, alloc, free" kram weg!
-
Und wenn du dir den ganzen Ärger mit der Speicherverwaltung ersparen willst, verwende lieber std::vector (o.ä.) anstelle der nackten Zeiger.
-
"unskilled" : Merkt man.

Mach doch mal C++ ... da sparst Du Dir und uns auch Deine Folgefrage der Art "Warum bekomme ich einen SeqFault ?", "Wieso fehlen da Zeichen ?", ...struct Pizza { unsigned long handle; //ein handle zum identifizieren (?; s.u.) string name; //Anzeigename string beschreibung; //Beschreibung dazu vector<float> preis; //preise }; typedef vector<Pizza> PizzaListe; typedef vector<PizzaListe> PizzaMenu; // Braucht man die wirklich als Typen oder reicht da nicht einfach eine entsprechende Variable ? ...Damit entällt jedes malloc(), realloc(), str___(), ... und alle möglicen anderen Komplikationen.
Übrigens @"Modellierung":
0.) "pizza_item" ist ein unglücklicher Name, weil er fachliche (soll eine Pizza abbilden) und technische (soll Bestandteil einer Liste sein) Bezeichnung mischt. Angesichts Deiner anderen "Benamsung" würde ich das Teil einfach "pizza" nennen. Was ein "PizzaMain" sein soll, weiß ich nicht...
1.) Ich würde mir gründlich überlegen, WAS eine Pizza identifizieren soll ... ob das wirklich ein "Handle" sein soll, oder ob nicht tatsächlich der name selbst die Pizza bereits eindeutig beschreibt. Was nützen Dir zwei verschiedene "Pizza Margerita" (die jeweils noch n verschiedene Preise haben können.... und welchen Ärger können sie Dir einhandeln ?
2.) Woran soll ein Nutzer den aktuellen Preis bestimmen, wenn er nur eine Liste von Preisen hat ? Wenn die jeweiligen Preise eine Bedeutung haben, sollte das über ein Attribut von preis ersichtlich sein ... so "unsichtbare Bedingungen" wie "Der 1. Preis ist immer der für Kunden, der 2. immer der für Angestellte, der 3. ...." beissen einem irgendwann immer in der Hintern. Das sollte auch direkt mit modelliert werden. Das geht z.B. über eintypedef pair<string, unsigned int> Preis; struct Pizza { // ... vector<Preis> preise; };oder direkt in der
struct Pizza { // ... map<string, unsigned int> preise; };(Alternativ kann natürlich auch ein enum zur "Preisart-Identifikation" dienen)
3.) Ich würde den Preis in Cent als unsigned int ablegen. Spart Dir Rundungsprobleme und feiner als Cent brauchst Du doch eh nicht.
Gruß,
Simon2.
-
danke für eure antworten - vor allem @simon :>
ich meld mich wieder, wenns nicht klappt bzw ich fragen hab ^^
@simon: die preise haben schon ne beschreibung - die ist in der liste (als beschreibung gekennzeichnet ^^)die idee mit dem preis als int und nicht als float fand ich auch ganz ok - und hab es auch direkt so gemacht - jz geht alles - warum auch immer ^^
danke : >
//edit habs jz auch mit new gemacht, aber irgendwie hab ich da was falsch gemacht

this->Main->lists[this->Main->listcount-1].beschreibung = new char*[PpI]; for (unsigned __int8 i = 0; i < PpI; i++) { this->Main->lists[this->Main->listcount-1].beschreibung[i] = new char; strcpy (this->Main->lists[this->Main->listcount-1].beschreibung[i], Beschreibungen[i]); }Ist hier irgend ein Fehler drin?
Weil, wenn ich danach von außen darauf zugreife, kommt nen doller Zugriffsfehler - bei Allem anderen aber ist alles in Ordnung
Danke schon mal und noch mal und überhaupt ^^Tom
-
ok - der Fehler lag/liegt nicht an der Schleife an sich sondern immer noch an (falschen) Speicherzugriffen :<
noch mal den Code, wie er jetzt ist:
//structs struct pizza_item { unsigned __int32 handle; char *name; char *beschreibung; unsigned __int16 *preis; }; struct pizza_list { unsigned __int16 id; char *name; char *beschreibungen; unsigned __int8 ppi; //Preise pro Item signed __int16 itemcount; pizza_item **items; }; struct pizza_main { signed __int16 listcount; pizza_list **lists; };und
void pizza::newmain (void) { this->Main = new pizza_main; this->Main->listcount = 0; this->Main->lists = new pizza_list *[]; } void pizza::addlist (unsigned __int16 ID, char *Name, char *Beschreibungen, unsigned __int8 PpI) { this->Main->lists[++this->Main->listcount-1] = new pizza_list; this->Main->lists[this->Main->listcount-1]->id = ID; this->Main->lists[this->Main->listcount-1]->ppi = PpI; this->Main->lists[this->Main->listcount-1]->name = new char[]; strcpy (this->Main->lists[this->Main->listcount-1]->name, Name); this->Main->lists[this->Main->listcount-1]->items = new pizza_item *[]; this->Main->lists[this->Main->listcount-1]->itemcount = 0; this->Main->lists[this->Main->listcount-1]->beschreibungen = new char[]; strcpy (this->Main->lists[this->Main->listcount-1]->beschreibungen, Beschreibungen); } void pizza::additem (unsigned __int16 ListNr, unsigned __int32 Handle, char *Name, char *Beschreibung, unsigned __int16 *Preise) { this->Main->lists[ListNr]->items[++this->Main->lists[ListNr]->itemcount-1] = new pizza_item; this->Main->lists[ListNr]->items[this->Main->lists[ListNr]->itemcount-1]->handle = Handle; this->Main->lists[ListNr]->items[this->Main->lists[ListNr]->itemcount-1]->name = new char[]; strcpy (this->Main->lists[ListNr]->items[this->Main->lists[ListNr]->itemcount-1]->name, Name); this->Main->lists[ListNr]->items[this->Main->lists[ListNr]->itemcount-1]->beschreibung = new char[]; strcpy (this->Main->lists[ListNr]->items[this->Main->lists[ListNr]->itemcount-1]->beschreibung, Beschreibung); this->Main->lists[ListNr]->items[this->Main->lists[ListNr]->itemcount-1]->preis = new unsigned __int16[this->Main->lists[ListNr]->ppi]; for (unsigned __int8 i = 0; i < this->Main->lists[ListNr]->ppi; i++) { Main->lists[ListNr]->items[Main->lists[ListNr]->itemcount-1]->preis[i] = Preise[i]; } }Ich weiß, dass es auch mit vector geht, aber ich seh keinen Vorteil darin, es anders zu machen - oder hab ich so nicht nur nen kleinen Fehler drin und es geht so gar nicht??? (glaub ich ja eigtl nicht dran, aber soll sich ja ne so anhören, als ob ich alles besser wüsste ^^)
Danke schon mal...

unskilled - da ist der Name Programm ^^
//eidt: hups - hatte da wirklich nen paar [] vergessen...
-
unskilled schrieb:
Ich weiß, dass es auch mit vector geht, aber ich seh keinen Vorteil darin, es anders zu machen
Solcher Code:
this->Main->lists[ListNr]->items[this->Main->lists[ListNr]->itemcount-1]->preis = new unsigned __int16[this->Main->lists[ListNr]->ppi];tut mir in den Augen weh. Dir nicht?
std::vector und std::string sind dafür da, dass du dich nicht um den dynamischen Speicher kümmern musst. Damit wird dein Code viel, viel einfacher und übersichtlicher.
unskilled schrieb:
oder hab ich so nicht nur nen kleinen Fehler drin und es geht so gar nicht???
Es geht so, wie du das hier anscheinend vorhast - aber dafür reichen deine Kenntnisse offenbar nicht aus. Dein Code ist voller Fehler, weil du von dynamischer Speicheralloziierung keine Ahnung hast.
Du alloziierst ein Array von Pointern ohne Größenangabe, du alloziierst einen einzelnen char und schreibst dann einen ganzen String hinein, usw.
Das, was du da vorhast, geht auch komplett ohne irgendwelche Zeiger oder new. Schmeiß den Code weg, und benutzt vector und string.
Und lass das mit dem "this->".
-
Du alloziierst ein Array von Pointern ohne Größenangabe
Dafür ist es doch eine dynamische Speicherverwaltung, damit das auch geht, oder hab ich das falsch verstanden?
btw: wenn ich die Länge statisch mache, wirds auch nicht besser...
du alloziierst einen einzelnen char und schreibst dann einen ganzen String hinein
Ja, das hatte ich wirklich vergessen

Danke...
-
unskilled schrieb:
Du alloziierst ein Array von Pointern ohne Größenangabe
Dafür ist es doch eine dynamische Speicherverwaltung, damit das auch geht, oder hab ich das falsch verstanden?
Dynamisch bedeutet nicht, dass sich das auf magische Art und Weise von selbst regelt. Dynamisch heißt hier nur, dass die Größe erst zur Laufzeit feststehen muss. Angeben musst du sie trotzdem.
Wenn du automatische Speicherverwaltung willst, nimm std::vector und std::string.
-
unskilled schrieb:
Dafür ist es doch eine dynamische Speicherverwaltung, damit das auch geht, oder hab ich das falsch verstanden?
Offensichtlich. Soll der Rechner raten wieviel Speicher Du brauchst?
Nee, dynamische Speicherverwaltung erlaubt Dir auch nur, dass Du Blöcke anfordern kannst deren Größe beim Compilieren noch nicht bekannt ist. Wunder kann C++ auch nicht vollbringen.
-
na gut : <
Danke ^^
-
unskilled schrieb:
...
//edit habs jz auch mit new gemacht, aber irgendwie hab ich da was falsch gemacht
...
Ist hier irgend ein Fehler drin?
Weil, wenn ich danach von außen darauf zugreife, kommt nen doller Zugriffsfehler - ...=>
Simon2 schrieb:
...Mach doch mal C++ ... da sparst Du Dir und uns auch Deine Folgefrage der Art "Warum bekomme ich einen SeqFault ?", "Wieso fehlen da Zeichen ?", ...
....Damit entällt jedes malloc(), realloc(), str___(), ... und alle möglicen anderen Komplikationen...."I told you so, i told you so, ...." :p :p
Sorry, ich habe keine Zeit für überflüssige Fehler.

Gruß,
Simon2.