Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Vektoren in C++ und Speichervergabe

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
04.08.2005, 16:19 Uhr
JazzMC



Falls diese Frage schon irgendwo beantwortet wird oder ihr einen tollen Link wisst, sagts ruhig damit :-)

Es geht um folgendes.

Ich schreibe an einem kleinen Programm für meine Diplomarbeit (Kantenfärbungen im vollständigen Graphen und lokale Suche), in dem Vektoren benutzt werden. Leider ereignet sich auch nach sorgfältigster Bug-Suche ein Fehler, der darauf zurückzuführen sein muss, nach allem, was ich mir an Testausgaben habe machen lassen, dass der Inhalt von Vektoren teilweise unsinnvollerweise überschrieben wird.

Der Vektor, in dem das passiert, wird ohn Größenangabe deklariert, also
vector<int> wasauchimmer;
und danach werden je nach Bedarf durch push_back() bzw. delete() Elemente eingefügt bzw. gelöscht. Das deswegen, weil ich die genaue Größe vorher nicht weiß und selbige auch variieren kann.

Soweit ich an verschiedener Stelle gelesen habe, verwalten diese Methoden automatisch den nötigen Speicher. Durch das Hinzufügen und Löschen kann es ja rein theoretisch sein, dass, wenn inzwischen im Speicher auch andere Datenobjekte angelegt wurden, die Speicherbausteine für einen Vektor nicht mehr alle hintereinander ohne Lücke liegen.

Meine Frage ganz genau: Wenn so etwas passiert, ist es dann ausgeschlossen, dass DADURCH Teile von Vektoren überschrieben werden, oder muss man, um so etwas vorzubeugen, Vektoren IMMER nach dem Schema
vector<int> (CONST GROESSE);
deklarieren?

Oder anders formuliert: ich habe den Code so lange nach möglichen falschen Indexbenutzungen (z.B. Vektor hat nur 8 Ints als Inhalt, aber ein Index greift auf vector[12] zurück) durchsucht, dass ich langsam den Eindruck gewinne, dass ich die Funktionsweise der Vektoren an sich vielleicht nicht richtig verstanden habe und das Ganze deswegen immer irgendwann durch eine Speicherfehlbelegung (inhaltlicher Art) abstürzt.

Und noch einmal anders: wenn die einzelnen Speicherbelegungen eines Vektors nicht mehr alle hintereinander, in Reih und Glied gewissermaßen liegen, kann das zu Fehlern führen, weil die Zugriffe vector[0], vector[1], vector[2], ... vector[n] immer auf aufeinander folgende Speicherelemente zugreifen, weil angenommen wird, dass diese immer so angeordnet sind?

Ganz übergeordnet: merkt sich die Programmverwaltung alle einzelnen Speicheradressen eines Vektors, auch wenn sie nicht aufeinanderfolgen, und achtet darauf, dass diese NICHT von anderen Datenobjekten belegt werden? Und wenn ich
vector.clear();
ausführe, dann andere Datenobjekte anlege, und dann durch die push_back()-Methode diesen eben geleerten Vektor wieder anfange zu füllen, wird dann wieder auf die vorher benutzten Speichereinheiten (der Vektors, bevor er geleert wurde) gespeichert, die ja jetzt rein theoretisch durch die neuen Datenobjekte belegt sein könnten (der Speicher wurde ja freigegeben), oder weiß die Programmverwaltung, dass dieser Speicher inzwischen zum Teil von anderen Variablen belegt wurde und weist dem gleichen Vektor neuen Speicher zu, wenn er wieder aufgefüllt wird?

Ziemlich lange Fragerei, ich weiß, aber ich habe über die Jahre festgestellt, dass es ganz sinnvoll sein kann, eine Frage auf verschiedene Arten und Weisen zu stellen, weil unterschiedliche Menschen ein Problem auf unterschiedliche Weise begreifen, und nur dann wirklich gute Antworten geben können, wenn die Problembeschreibung ihrer Auffassung von selbigem gleicht. So ging es mir immer in Physik ;-)

Ich hoffe, irgendjemand kennt die C++ Innereien so gut, dass er mich erleuchten kann. Langsam verzweifle ich nämlich an diesen vielleicht 200 Zeilen Code. Die kann ich auch gerne bei Bedarf hier reinkopieren, aber ich denke, dass die Frage erstmal spezifisch genug ohne ihn ist.

Cheers,

Jan.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
04.08.2005, 16:40 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat von JazzMC:
Falls diese Frage schon irgendwo beantwortet wird oder ihr einen tollen Link wisst, sagts ruhig damit :-)

Es geht um folgendes.

Ich schreibe an einem kleinen Programm für meine Diplomarbeit (Kantenfärbungen im vollständigen Graphen und lokale Suche), in dem Vektoren benutzt werden. Leider ereignet sich auch nach sorgfältigster Bug-Suche ein Fehler, der darauf zurückzuführen sein muss, nach allem, was ich mir an Testausgaben habe machen lassen, dass der Inhalt von Vektoren teilweise unsinnvollerweise überschrieben wird.



Tja, ohne Code wahrscheinlich schwer beurteilbar...


Zitat von JazzMC:

Der Vektor, in dem das passiert, wird ohn Größenangabe deklariert, also
vector<int> wasauchimmer;
und danach werden je nach Bedarf durch push_back() bzw. delete() Elemente eingefügt bzw. gelöscht. Das deswegen, weil ich die genaue Größe vorher nicht weiß und selbige auch variieren kann.


Bishierhin erstmal kein prinzielles Problem.


Zitat von JazzMC:

Soweit ich an verschiedener Stelle gelesen habe, verwalten diese Methoden automatisch den nötigen Speicher. Durch das Hinzufügen und Löschen kann es ja rein theoretisch sein, dass, wenn inzwischen im Speicher auch andere Datenobjekte angelegt wurden, die Speicherbausteine für einen Vektor nicht mehr alle hintereinander ohne Lücke liegen.

Meine Frage ganz genau: Wenn so etwas passiert, ist es dann ausgeschlossen, dass DADURCH Teile von Vektoren überschrieben werden, oder muss man, um so etwas vorzubeugen, Vektoren IMMER nach dem Schema
vector<int> (CONST GROESSE);
deklarieren?



Nein. Wenn Du mitten im vector was löschst, wird die Lücke automatisch geschlossen. Ein Vector garantiert, daß es niemals zu Lücken kommt.

Stell Dir unter einem Vector ein Array vor, wobei Dir der Vector folgende Features schenkt:
1. Beim einfügen wird der Vector nach bedarf erweitert.
2. Beim einfügen werden alle nachfolgende Elemente entsprechend nach hinten verschoben
3. Beim löschen werden die Lücken automatisch geschlossen.
4. Einfüge/Löschoperationen haben O(n) Komplexität
5. Es ist garantiert, daß die elemente in einem Zusammenhängen Speicherbereich hintereinander liegen.

Für die Arrayzugriffe, also a[10] kannst Du auch a.at(10) verwenden. Letztere Variante ist geringfügig langsamer aber macht range-checks und wirft Exceptions im Falle das der Index nicht korrekt war.

200 Zeilen sind ja nicht die Welt. Probier mal ein wenig zu cutten, so daß man einen ungefähren Eindruck des Source bekommt...
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
04.08.2005, 22:20 Uhr
JazzMC



Danke schonmal für diese Erläuterungen :-)

Vielleicht kannst du ja noch eine weitere Frage beantworten; dann wüsste ich wahrscheinlich, welche Möglichkeiten es noch gibt, dass dieser fehler auftritt.

Nehmen wir an, ich erzeuge einen Vektor (ohne Größenangabe). Packe da 3 Integer-Werte rein. Dann wird der Vektor erstmal nicht benutzt, aber dafür lege ich weitere Vektoren an. Einer dieser Vektoren wird relativ nahe am ersten erzeugten im Speicher abgelegt. Nehmen wir mal an, dass von Ende des ersten (mit den 3 Integers) bis zum Anfang eines der weiteren 22 Plätze für Integer-Speicher liegen.

Jetzt werden wieder Integers in den ersten Vektor reingepackt, mit push_back(). Es sind 40 Integer-Werte.

Was passiert?

Wenn, wie du sagst, garantiert würde, dass bei einem Vektor alle Elemente in einnem zusammenhängenden Speicherbereich liegen, kann es ja gut sein, dass jetzt sehr viel verschoben werden muss, um die Lücke für den erstangelegten Vektor so groß zu machen, dass da jetzt 43 Integers nebeneinander liegen können.

Ich frage deshalb, weil ich genau diese Konstellation in meinem Programm gegeben ist. Wenn du jetzt sagst, dass tatsächlich alles verschoben wird, was sonst noch so existiert, um diesem einen Vektor zu erlauben, alle Werte am Stück zu speichern, oder wenn der Vektor selbst woanders hin verschoben wird, wo genug Platz ist, das Verschieben aber jeweils so passiert, dass KEIN SCHON BELEGTER Speicher überschrieben wird, bedeutet das, dass der Fehler irgendwo anders liegen muss.

Und das war's ja, dessen ich mich vergewissern wollte.

Cheers,

Jan.

PS: Code könnte ich schon hier reintun, und werde ich auch, wenn's notwendig wird. Aber die Frage oben kann man ja auch ohne beantworten, und ich will es ehrlich gesagt niemandem antun, meinen Code auseinanderzuklamüstern ;-)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
05.08.2005, 08:17 Uhr
virtual
Sexiest Bit alive
(Operator)


Wenn ich im Programm zwei Vectoren habe, die ihren Speicher dierekt hintereinander haben, dann wird - falls der erste Vector vergrößert wird - komplett verschoben.

Wenn Du unter Linux arbeitest, dann kannst Du ja mal valgrind benutzen. Das ist ein Memory debuigger, welcher zeigt wo es knallt.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
05.08.2005, 09:30 Uhr
(un)wissender
Niveauwart


@JazzMC
Ich glaube, du solltest dir über das Speichermanagement von std::vector<int> keine Gedanken machen. Da gbt es nichts, was du beachten oder falsch machen könntest.Anderes sieht es mit Pointern im Vector aus, die mit new erzeugt wurde, aber das ist eine andere Geschichte.
Vielleicht hast du ja doch einen Indexfehler? Die Funktion at des vectors überprüft beim Zugriff die Vectorgrenzen. Vielleucht übergibtst den vector ja auch mal per value an Funktionen und veränderst damit nur eie lokale Kopie und nicht den eigentlich Vector. Ansonsten zeig mal Code.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
05.08.2005, 11:10 Uhr
JazzMC



Danke für die Hinweise!

Dann muss es irgendwo eine Indexüberschreitung sein.

Gott allein weiß wo ...

Das mit der at-Funktion klingt gut, werde ich mal testen.

Und sollte ich kläglich scheitern, werde ich hier mal den Code reinstellen. Das ist bestimmt irgendwas hirnrissig simples.

Cheers,

Jan.


-------------------------------------------------------------
Usually, 12 out of 10 people will tell you that they like chocolate
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: