Registriert: So Okt 21, 2007 14:16 Beiträge: 123
Programmiersprache: Delphi
Hallo,
bei einem Programm ist es mir passiert, dass sich ein Record nach einer Vergrößerung eines dynamischen Arrays plötzlich ändert und nur noch leere Daten enthält. Im Anhang habe ich zwei Screenshots (links: vorher, rechts nachher. Dazwischen steht SetLength(result, length(result)+1). Hat jemand ne Idee, woran das liegen kann bzw. was man dagegen machen kann?
Gruß Joni.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Gib mal den Code drumherum... Das klingt mir doch sehr merkwürdig.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
vermutlich liegt es daran dass dynamische Arrays Pointer und nicht Value Semantik bei zuweisungen hat. SetLength jedoch das wieder aufhebt. Da solltest du unbedingt nochmal die Referenz zu dynamischen arrays lesen.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Also ich muss gestehen, dass ich den Code etwas verwirrend finde. Aber das kann auch einfach daran liegen, dass ich nicht weiß was der Code machen soll. Allerdings habe ich da so eine Vermutung.
Hier ein kleines Beispiel was du ja in deinem Code so ähnlich machst. Wenn ich das richtig gesehen habe.
Code:
type
PBlub =^TBlub;
TBlub =record
...
end;
TBlubArray =arrayof TBlub;
var
Blub: PBlub;
BlubArray: TBlubArray;
begin
SetLength(BlubArray,1);
Blub :=@BlubArray[0];
SetLength(BlubArray,2);// Hier wirds lustig
end;
SetLength setzt die Größe eines dynamischen Arrays. Dabei kann es passieren, dass der neue Speicherbedarf im Vergleich zu vorher wächst. Nicht ungewöhnlich. Aber es kann passieren, dass das neue Array so groß wird, dass es nicht mehr an der gleichen Stelle im Speicher bleiben kann. Weil zum Beispiel direkt hinter dem Array noch etwas anderes abgelegt wurde. Dann MUSS das komplette Array verschoben werden. SetLength kopiert den Inhalt automatisch an die neuen Speicherstelle aber die Adresse des Arrays bzw. der Elemente haben sich verändert. Wenn du dir aber einen Pointer auf ein Element gemerkt hast, dann wird der auf einen anderen (falschen) Speicherbereich zeigen.
Direkt nach dem Verschieben des Arrays hat der Speicher an der vorherigen Stelle vermutlich noch gültige Werte. Wenn du also dann darauf zugreifst wirst du noch passende Werte bekommen. Allerdings wenn dazwischen anderer Code ausgeführt wird, der Speicher haben will, dann kann es sein, dass dieser Speicher wieder für etwas benutzt wird. Und genau dann kann zu solch einem Problem kommen.
Also niemals einen Pointer auf Arrayelemente merken, wenn sich das Array in der Größe verändern kann. Ich persönlich bevorzuge bei solchen Konstruktionen grundsätzlich eine vollständig eigene Verwaltung. Also ich würde die kleinen Elemente alle mit new(PCutPoint variable) erstellen und dann hat man nur einen Pointer. Dann kann nichts passieren, da dieser Pointer nicht verschoben wird. Den Pointer kannst du dann auch in ein array packen. (oder gleich verketete Listen benutzen) Allerdings Pointer auf Arrayelemente sind trotzdem tabu. Nur direkt die Werte des Arrays. Den Speicher den du mit New erzeugst solltest du mit Dispose wieder frei geben.
Registriert: So Okt 21, 2007 14:16 Beiträge: 123
Programmiersprache: Delphi
Hallo,
das mit der Längenänderung und der Verschiebung im Speicher hatte ich mir auch erst gedacht, aber es ist ein wenig anders, deswegen habe ich mich auch etwas gewundert:
Code:
var
array1, array2:arrayof Blub;
p1:^Blub;
begin
SetLength(array1,1);
p1 :=@array1[0];
SetLength(array2,10);//Jetzt ist p1 ungültig
end;
Was Lossy eX mir geraten hat, probiere ich jetzt aus. Schonmal Vielen Dank.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Joni hat geschrieben:
das mit der Längenänderung und der Verschiebung im Speicher hatte ich mir auch erst gedacht, aber es ist ein wenig anders, deswegen habe ich mich auch etwas gewundert:
Code:
var
array1, array2:arrayof Blub;
p1:^Blub;
begin
SetLength(array1,1);
p1 :=@array1[0];
SetLength(array2,10);//Jetzt ist p1 ungültig
end;
Also der Pointer auf das Element muss nicht zwingen ungültig werden. Wenn der Speicher passt wird es gültig bleiben. Allerdings das kann man nie so genau sagen. In deinem Code von Eben müsste p1 allerdings noch gültig sein. Du benutzt ja schließlich ein anderes Array. Aber in deinem richtigen Code habe ich ehrlich nicht genau sehen können woher welches Array stammt.
Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.