Hallo, Ich beschäftige mich mit folgendem. Ich möchte in einem c++ Programm Objekte mit New anlegen. Ferner sind in diesen Objekten Pointer auf andere Objekte. Soweit so gut. Jetzt will ich aber die Objekte in einem Vector ablegen. Ich will die Vector klasse nutzen. Aber die Vector klasse ist ja dynamisch. Was passiert wenn die Vector klasse Die Objekte in einen anderen Speichervereich verlegt dann stimmen die Referenzen der Pointer ja nicht mehr. Dieses Problem habe ich nämlich bei einem c++ Programm mit einem avr32. Es wurde behauptet das auf dem pc die Vector Klassen diese Probleme alle automatisch lösen würde. Aber auf dem avr32 ist es definitiv nicht so Wenn dort die Objekte durch eine reallocation im Speicher verschoben werden wird nicht automatisch ein zuvor gespeicherter ponter Wert im Objekt mit verschoben. Kann jemand dazu etwas sagen ?
Jens A. schrieb: > Kann jemand dazu etwas sagen ? also Vector arbeiten überall gleich. Wie verschiebst du denn ein Objekt im speicher? ein Objekt was mit new angelegt ist, bleibt dort wo es ist. Es gibt gar keine Möglichkeit es zu verschieben.
Gib mal ein Code-Beispiel, ich bin mir nicht sicher, ob ich verstehe was
du meinst.
Im Prinzip würde ich eher Pointer auf Objekte in einem Vektor speichern,
nicht die Objekte selber, also std::vector<mytype*> statt
std::vector<mytype> -- außer, mytype sind wirklich nur 2 ints oder so.
> Es gibt gar keine Möglichkeit es zu verschieben.
Naja, geht schon, memcpy und dann free. Macht man nur i.d.R. nicht
(warum auch). std::vector macht das mit Sicherheit nicht, das wäre ja
Absturzursache Nummer 1.
Gruß,
Sven
Hallo Also wir nutzen einen avr32. Dort haben wir New trivial selber implementiert Und zwar einfach mit malloc. Ist das ok. Ist New = malloc? Nun haben wir einen Vector Beim ersten mal wenn wir ein object in den Vector schieben Wird ein malloc gemacht. Wird ein zweites object reingeschoben wird realloc gemacht. Auch kein Problem. Wird aber auf dem Heap jetzt etwas anderes gemacht wird direkt nach den 2 Objekten Ja Speicher belegt. Wenn jetzt aber wieder ein object in den zuvor genutzten Vector reingeschoben wird Muss realloc die kompletten Objekte wo anders in den Speicher kopieren da der zuvor zusammenhängende Speicher durch ein zwischenzeitlich auftretendes New belegt ist. Somit verschieben sich die Objekte im Speicher. Laut Vector klasse darf man ja reinlegen was Mann will also auch Objekte. Oder?
Jens A. schrieb: > Laut Vector klasse darf man ja reinlegen was Mann will also auch > Objekte. > Oder? ja aber diese dingen müssen Kopierbar sein. das heist bei dir muss der zuweisungsoperator und der 2. Contruktur sauber funktionieren operator=(const& obj) obj(const& obj)
Jens A. schrieb: > Ist New = malloc? Jein (es macht mehr außer malloc), aber wenn Ihr schon C++ nehmt warum baut Ihr dann Dinge fehlerträchtig nach die bereits implementiert sind ? Wenn Ihr Klassen verwalten wollt dann nehmt ein Template und verwaltet sie intern als Liste oder Array, je nach gusto und Speichereffizienz. Es macht keinen Sinn ein einmal angelegtes Objekt umzukopieren wenn man doch den Pointer darauf hat !
Ich verstehe das Problem nicht ganz. Zeig mal den Code. Der Fehler liegt sicher bei dir, nicht in std::vector. ;)
cppler schrieb: > Jens A. schrieb: >> Ist New = malloc? > > Jein (es macht mehr außer malloc), aber wenn Ihr schon C++ nehmt warum > baut Ihr dann Dinge fehlerträchtig nach die bereits implementiert sind ? > Wenn Ihr Klassen verwalten wollt dann nehmt ein Template und verwaltet > sie intern als Liste oder Array, je nach gusto und Speichereffizienz. > Es macht keinen Sinn ein einmal angelegtes Objekt umzukopieren wenn man > doch den Pointer darauf hat ! Hallo wir kopieren Objekte ja nicht gewollt um. Das kommt von der Vector klasse. Mich würde eben interessieren ob das auf dem pc mit der Vector klasse genauso ist. Kann es da passieren das wenn ich Objekte in einen Vector lege es dazu kommen kann wenn der Vector dynamisch wächst das auf dem pc die Objekte in einen anderen Speichervereich kopiert werden ? Dadurch würden ja zuvor gespeicherte Pointer auf ein Objekt ihre Gültigkeit verlieren? New haben wir neu gemacht da aus irgendwelchen gründen es Probleme mit dem New für den avr32 gibt. Unser Programm startet dann gar nicht.
Jens A. schrieb: > wir kopieren Objekte ja nicht gewollt um. Das kommt von der Vector > klasse. Zeig doch mal den Code. Sonst ist das alles nur blabla hier.
Jens A. schrieb: > wir kopieren Objekte ja nicht gewollt um. Das kommt von der Vector > klasse. ja das ist auch normal > Mich würde eben interessieren ob das auf dem pc mit der Vector klasse > genauso ist. ja ist es > Kann es da passieren das wenn ich Objekte in einen Vector lege es dazu > kommen kann wenn der Vector dynamisch wächst das auf dem pc die Objekte > in einen anderen Speichervereich kopiert werden ? Dadurch würden ja > zuvor gespeicherte Pointer auf ein Objekt ihre Gültigkeit verlieren? aus dem grund darf man sich auch kein zeiger auf ein objekt merken das in einem vektor liegt. Aus dem Grund speichert man zeiger im vektor > New haben wir neu gemacht da aus irgendwelchen gründen es Probleme mit > dem New für den avr32 gibt. Unser Programm startet dann gar nicht. prima, ihr versucht also ein Problem zu umgehen, das hier nicht mal verstanden habt.
Peter 2 schrieb >>aus dem grund darf man sich auch kein zeiger auf ein objekt merken das >>in einem vektor liegt. Aus dem Grund speichert man zeiger im vektor Danke für die Auskunft. Sind andere auch der Meinung? Es wurde nämlich behauptet auf einem pc wäre das nicht schlimm Dort kann man Objekte in einem Vector Speicher. Wenn jetzt das object a auf object b zeigt und die Objekte werden verschoben im Speicher würde auf dem pc das mit den Pointern automatisch richtig gestellt. Das kann ich aber nicht glauben
Jens A. schrieb: > Es wurde nämlich behauptet auf einem pc wäre das nicht schlimm > Dort kann man Objekte in einem Vector Speicher. kann man auch, nur darf man sich keine zeiger auf objekte merken > Wenn jetzt das object a auf object b zeigt und die Objekte werden > verschoben im Speicher würde auf dem pc das mit den Pointern automatisch > richtig gestellt. nein - wer soll das denn machen? > Das kann ich aber nicht glauben ich auch nicht.
Hallo Peter Danke schon mal für die Infos. Hat eventuell jemand anders schon mal c++ auf dem avr32 genutzt?
Peter II schrieb: > Jens A. schrieb: >> wir kopieren Objekte ja nicht gewollt um. Das kommt von der Vector >> klasse. > ja das ist auch normal Nenn' mal bitte ein Beispiel für dieses Verhalten (Code). Wann passiert das denn?
Jens A. schrieb: > Hat eventuell jemand anders schon mal c++ auf dem avr32 genutzt? Du hast es immer noch nicht. Das hat nichts mit avr32 zu tun! Das ist eine reine Frage dessen, ob du deine Klasse richtig aufgebaut hast oder nicht. Dein Objekt betreibt anscheinend selbst Resource Mangement (aus welchem Grund auch immer). Dazu muss aber der Copy-Constructor und der Zuweisungsoperator, sowie der Destruktor richtig geschrieben sein. Also zeig endlich Code und hör auf um den heißen Brei herumzureden! Dann kann man entscheiden, welche Strategie die richtige ist: * die Klassen korrigieren * im Vector nur Pointer speichern Alles hängt davon ab, wie die Beziehung der Objekte zueinander ist.
Hallo, also so
1 | inline void *operator new(size_t size) |
2 | {
|
3 | void* data = malloc(size); |
4 | |
5 | if (!data) |
6 | printf("Warning!!!!!!!!!!!!!!!11\r\n"); |
7 | //else
|
8 | //memset(data,0,size);
|
9 | |
10 | return data; |
11 | }
|
habne wir new überladen
Jens A. schrieb: > Aber die Vector klasse ist ja > dynamisch. Was passiert wenn die Vector klasse > Die Objekte in einen anderen Speichervereich verlegt dann stimmen die > Referenzen der Pointer ja nicht mehr. Nochmals ganz langsam, zum mitdenken: Fall a) Du hast ein Objekt mit new angelegt, auf das innerhalb deines Programms Referenzen (Pointer oder Refrenzen) zeigen. Wenn du ein dieses Objekte in einem Vector speichern willst, musst du das da hinein-KOPIEREN. Du hast danach zwei Objekte, das Original und die Kopie im Vektor. Alle Refenzen zeigen natürlich weiterhin auf das Original. Wenn du das Original-Objekt löscht, sind alle Referenzen darauf nicht mehr gültig. Ob die Vectorklasse intern das kopierte Objekt noch weiter hin- und herkopiert, ist dabei völlig egal. Du kannst sowieso nirgends mehr eine gültige Referenz auf das Objekt im Vector haben. Wenn du dagegen innerhalb des Objektes Referenzen auf interene Strukturen des selben Objektes nutzt (warum auch immer), dann muß der Copykontruktor diese beim Kopieren entsprechend aktualisieren, sonst könntest du ja keine funktionerenden Kopiene erzeugen. Das klappt dann auch innerhalb des Vectors, wenn dort die Elemente dynamisch um-KOPIERT werden. Wo also ist jetzt genau dein Problem? Oliver
Dein new tut nicht dasselbe wie new in C++. Es initialisiert den Speicher nicht. Was soll das überhaupt bringen, dieses Konstrukt? Benutz' doch einfach malloc.
Sven B. schrieb: > Dein new tut nicht dasselbe wie new in C++. Nicht den globalen operator new mit der Operation new verwechseln. operator new ist nur dafür zuständig Speicher zu besorgen. Dass auf diesem Speicher dann der Konstruktor losgelassen wird ... darum kümmert sich der Compiler. > Speicher nicht. Was soll das überhaupt bringen, dieses Konstrukt? Frag ich mich auch. Einzig ein nicht funktionsfähiges new in der Runtime Lib wäre ein Grund da einzugreifen. Oder eben Schnickschnack wie Memory Überwachung. Aber die generelle Empfehlung lautet: lass den globalen operator new in Ruhe. > Benutz' doch einfach malloc. Das ist schlechter Rat. In C++, speziell wenn Klassen im Spiel sind, hat malloc eigentlich nur noch in Ausnahmefällen etwas zu suchen. Wo allerdings im Code des TO ein Aufruf von realloc herkommen soll, ist mir nicht ganz klar. In C++ gibt es keinen realloc (d.h. natürlich gibt es die Funktion. Aber im Zusammenspiel mit new/delete ist die nicht verwendbar)
Karl Heinz Buchegger schrieb: > Wo allerdings im Code des TO ein Aufruf von realloc herkommen soll, ist > mir nicht ganz klar. von vector, wenn er sich vergößert.
Karl Heinz Buchegger schrieb: > Sven B. schrieb: >> Dein new tut nicht dasselbe wie new in C++. > > Nicht den globalen operator new mit der Operation new verwechseln. > > operator new ist nur dafür zuständig Speicher zu besorgen. Dass auf > diesem Speicher dann der Konstruktor losgelassen wird ... darum kümmert > sich der Compiler. Ah. Okay. >> Benutz' doch einfach malloc. > > Das ist schlechter Rat. > In C++, speziell wenn Klassen im Spiel sind, hat malloc eigentlich nur > noch in Ausnahmefällen etwas zu suchen. Stimmt -- ziehe ich zurück. Irgendwie dachte ich, es geht um C.
Peter II schrieb: > Karl Heinz Buchegger schrieb: >> Wo allerdings im Code des TO ein Aufruf von realloc herkommen soll, ist >> mir nicht ganz klar. > > von vector, wenn er sich vergößert. kommt auf die konkrete vector implementierung an. Aber im allgemeinen kann std::vector keinen realloc benutzen. Wenn std::vector den Speicher vergrößert, MUSS es neuen Speicher anlegen und die einzelnen Objekte (so es welche sind) umkopieren, damit der Copy Konstruktor bzw. der op= aufgerufen wird. Gut für einen std::vector der Pointer oder POD hält, kann das template natürlich spezialisiert werden, um das Mem-Management mittels malloc/free zu erledigen. Aber sobald man Klassen im vector speichert, geht das nicht mehr.
Karl Heinz Buchegger schrieb: > Wenn std::vector den Speicher vergrößert, MUSS es neuen Speicher anlegen > und die einzelnen Objekte (so es welche sind) umkopieren, damit der Copy > Konstruktor bzw. der op= aufgerufen wird. Ich konnte auf die Schnelle jetzt nicht rausfinden, welcher der beiden benutzt wird, in allen Referenzen die ich geprüft habe ist immer nur die Rede von 'kopieren', also denke ich mal, dass std::vector diesen Job mit dem Copy Constructor erledigt. Macht auch am meisten Sinn.
Karl Heinz Buchegger schrieb: > Wenn std::vector den Speicher vergrößert, MUSS es neuen Speicher anlegen > und die einzelnen Objekte (so es welche sind) umkopieren, damit der Copy > Konstruktor bzw. der op= aufgerufen wird. warum? wenn er seinen eignene speicher mit realloc vergrößern kann, dann muss er doch nicht umkopieren. (gilt nur wenn die adresse gleich bleibt)
Jens A. schrieb: > habne wir new überladen Jens. Deine Objekte, die du im vector speicherst, bzw. deren verpointerte Querreferenzen zu anderen Objekten sind das Interessante! Dort entscheidet sich, wie die richtige Vorgehensweise ist. Dass du malloc aufrufen kannst, glauben wir dir unbesehen. Aber das ist nicht die Frage, die zur Lösung deines Problems beiträgt.
Peter II schrieb: > warum? wenn er seinen eignene speicher mit realloc vergrößern kann, dann > muss er doch nicht umkopieren. (gilt nur wenn die adresse gleich bleibt) Hier http://stackoverflow.com/questions/8003233/does-stdvector-have-to-move-objects-when-growing-capacity-or-can-allocator ist eine Diskussion über das Thema In a nutshell: Es muss das tun, weil ihm das der Standard so vorschreibt und eine entsprechende Erweiterung es nicht in C++11 geschafft hat. Die Erweiterung ist notwendig, weil realloc() im Grunde auch die falsche Funktion ist. Was man bräuchte ist eine Funktion mit der Semantik: vergrößere den allokierten Speicher wenn möglich und wenn das nicht geht, dann liefere mir einen Pointer auf frisch allokierten uninitialisierten Speicher. Denn mit realloc würde man die Kopieraktion 2 mal machen. Einmal wenn realloc eine bitweise Kopie anlegt und das zweitemal, wenn std::vector dann die Objekte in diesem Speicher copy-constructed. Da aber (auf größeren Systemen als einem AVR) davon auszugehen ist(*), dass realloc in den seltsten Fällen es schafft entsprechenden Speicher einfach zu erweitern sondern in die Kopiererei geht (man hat ja nicht nur einen std::vector im Programm), handelt man sich einen Penalty ein. Eine 'Optimierung' die in Wirklichkeit in der Mehrzahl der Fälle eine Verschlechterung ist. (*) und das wurde sicherlich auch empirisch rausgemessen, als die Semantik festgelegt wurde. (**) alles festgemacht am allgemeinen Fall. Dass es Sonderfälle (POD) gibt, ist davon nicht betroffen.
Karl Heinz Buchegger schrieb: > Denn mit realloc würde man die Kopieraktion 2 mal machen. Einmal wenn > realloc eine bitweise Kopie anlegt und das zweitemal, wenn std::vector > dann die Objekte in diesem Speicher copy-constructed. Humpf. Mein Fehler. Nicht mitgedacht. Das geht ja gar nicht. Wenn realloc umkopieren muss, wird der alte Speicher von realloc freigegeben. D.h. std::vector hat dann das Original gar nicht mehr, welches es benötigen würde um die Kopien zu copy constructen.
Hallo, Danke für die reichlichen Antworten. 1. ich denke ich muss erst mal herausfinden warum mein Programm wenn ich das New aus der stdlibc++ nehme nicht startet. Im übrigen das ist der FCC aus der atmel toolchain 2. @karl Heinz buchegger Ja ich denke auch das Problem ist das wenn bei meiner Implementierung ein realloc ein Objekt im Speicher verschiebt alte Pointer Referenzen nicht mehr gültig sind. 3. In welchen Spezifikationen steht eigentlich wie genau New funktioniert und was es macht Das muss doch mal ein spezifiziert haben oder?ä 4 Eventuell kann jemand mal Feedback geben der die atmel toolchain verwendet und auch c++ verwendet ob er auch Probleme mit New hat 5 Was macht eigentlich ein copy constructor und wie sieht so einer Beispieleise aus?
Jens A. schrieb: > Was macht eigentlich ein copy constructor und wie sieht so einer > Beispieleise aus? suche doch einfall mal bei google, kann doch nicht so schwer sein. Was wird er wohl machen - ein objekt kopieren?
Peter II schrieb: > Jens A. schrieb: >> Was macht eigentlich ein copy constructor und wie sieht so einer >> Beispieleise aus? > > suche doch einfall mal bei google, kann doch nicht so schwer sein. > > Was wird er wohl machen - ein objekt kopieren? Ja laut google suche kopiert der copy constructor auch nur Dateneingabe des alten Objekts. Realloc macht das genauso hält nur byteweise ohne die Datenstrukturen zu kennen
Jens A. schrieb: > Ja laut google suche kopiert der copy constructor auch nur Dateneingabe > des alten Objekts. du kannst da grundsätzlich machen was du willst, sinnvoll ist natürlich seine daten zu kopieren > Realloc macht das genauso hält nur byteweise ohne die Datenstrukturen zu > kennen das ist doch schon ein wichtiger unterschied - was willst du noch wissen.
Jens A. schrieb: > Hallo > > wir kopieren Objekte ja nicht gewollt um. Das kommt von der Vector > klasse. > Mich würde eben interessieren ob das auf dem pc mit der Vector klasse > genauso ist. Das ist bei allen konformen Implementationen so, allerdings nur dann, wenn der vector mehr Platz braucht, als er noch übrig hat. Ein vector hat eine Größe, die angibt, wieviele Objekte sich gerade darin befinden. Außerdem hat er eine Kapazität, die angibt, für wieviele Objekte insgesamt Platz wäre. Wenn man nun so viele neue Objekte in den vector legt, daß er größer sein müßte als die bisherige Kapazität, wird reallokiert, um die Kapazität zu vergrößern. Man kann mit reserve() auch explizit die Kapaziät erhöhen, um spätere Reallokationen zu vermeiden. Das bietet sich vor allem an, wenn man vorher genau weiß, wieviele Objekte insgesamt in den Vektor reinkommen werden. > Kann es da passieren das wenn ich Objekte in einen Vector lege es dazu > kommen kann wenn der Vector dynamisch wächst das auf dem pc die Objekte > in einen anderen Speichervereich kopiert werden ? Dadurch würden ja > zuvor gespeicherte Pointer auf ein Objekt ihre Gültigkeit verlieren? Ja. Man könnte aber z.B. statt eines Pointers einen Index in den Vektor nutzen. Sofern du neue Objekte nur am Ende anhängst, ändert sich der Index der schon bestehenden Objekte ja auch bei einer Reallokation nicht. Karl Heinz Buchegger schrieb: > Ich konnte auf die Schnelle jetzt nicht rausfinden, welcher der beiden > benutzt wird, in allen Referenzen die ich geprüft habe ist immer nur die > Rede von 'kopieren', also denke ich mal, dass std::vector diesen Job mit > dem Copy Constructor erledigt. Macht auch am meisten Sinn. Er darf meines Wissens auch default-konstruieren und dann zuweisen.
Wobei bei der Zuweisung selbstverständlich genauso der Copykonstuktor aufgerufen wird. Oliver
Oliver schrieb: > Wobei bei der Zuweisung selbstverständlich genauso der Copykonstuktor > aufgerufen wird. nein dafür gibt es den Zuweisungsoperator - das sind 2 verschiedene.
Jens A. schrieb: > 2. > @karl Heinz buchegger > Ja ich denke auch das Problem ist das wenn bei meiner Implementierung > ein realloc ein Objekt im Speicher verschiebt alte Pointer Referenzen > nicht mehr gültig sind. ganz ehrlich? Ich denke dass es 2 Möglichkeiten gibt * entweder ist der Ansatz Objekte im vector zu speichern schon der falsche, weil du dir keine Pointer in den vector merken darfst. * oder aber deine Klasse ist von der Sorte, dass sie eigentlich einen angepassten Copy Constructor brauchen würde, den du aber nicht hast. Die Entscheidung, welche der beiden Möglichkeiten die richtige ist, kann man aber erst treffen, wenn du endlich mal deine Klassen und wie sie zusammenhängen herzeigen würdest. Und da du diese Aufforderung jetzt schon zuuuuu lange ignorierst, bin ich raus aus der Sache. Ich hab keine Lust mehr mit Leuten zu diskutieren, die nicht wissen was ein Copy Constructor ist, die aber darauf beharren, dass der Compiler einen Fehler macht und nicht sie.
Karl Heinz Buchegger schrieb > Ich hab keine Lust mehr mit Leuten zu > diskutieren, die nicht wissen was ein Copy Constructor ist, die aber > darauf beharren, dass der Compiler einen Fehler macht und nicht sie. Also ich sage nicht das der Compler ein Fehler macht. Eigentlich ist jetzt alles geklärt. 1. Mein Fehler war, dass ich Objecte in einem Vector gespeichert habe. Jedes Object aber hat einen Pointer auf das nächste Object welches im Vector liegt. Wie eine verkettete Liste. Jedoch wird beim resize durch realloc die Objekte im Speuicher verschoben. Somit stimmen die Pointer nicht mehr. Das war ja mein eigentliches Problem und das hab ich durch die unterstürtzung begriffen danke. 2. Es kamen hat daher missverständnisse das jemand behauptet hat wenn man wie in 1 beschreiben sowas auf einem PC machen würde der Compiler automatisch alles richtig macht mit den Pointern. Das ist abe nicht der Fall uns somit ist das auch beantwirten.
Jens A. schrieb: > 1. Mein Fehler war, dass ich Objecte in einem Vector gespeichert habe. > Jedes Object aber hat einen Pointer auf das nächste Object welches im > Vector liegt. > Wie eine verkettete Liste. Und warum nimmst du dann nicht gleich ein std::list? Es gibt in der STL noch mehr Container als nur den std::vector
Jens A. schrieb: > 1. Mein Fehler war, dass ich Objecte in einem Vector gespeichert habe. > Jedes Object aber hat einen Pointer auf das nächste Object welches im > Vector liegt. > Wie eine verkettete Liste. Das würde ich dann doch gerne mal als Code sehen... Oliver
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.