Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 11:19

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Merkwürdige Datenänderung
BeitragVerfasst: So Aug 03, 2008 14:25 
Offline
DGL Member

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.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Aug 03, 2008 14:40 
Offline
DGL Member
Benutzeravatar

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 networkmy 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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Aug 03, 2008 16:03 
Offline
DGL Member

Registriert: So Okt 21, 2007 14:16
Beiträge: 123
Programmiersprache: Delphi
Hallo,

hab mal den relevanten Code hochgeladen.

Gruß Joni.


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Aug 04, 2008 09:15 
Offline
DGL Member

Registriert: Di Jun 06, 2006 09:59
Beiträge: 474
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.

_________________
Bild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Aug 04, 2008 10:42 
Offline
DGL Member
Benutzeravatar

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:
  1. type
  2.   PBlub = ^TBlub;
  3.   TBlub = record
  4.     ...
  5.   end;
  6.   TBlubArray = array of TBlub;
  7.  
  8. var
  9.   Blub: PBlub;
  10.   BlubArray: TBlubArray;
  11. begin
  12.   SetLength(BlubArray, 1);
  13.   Blub := @BlubArray[0];
  14.  
  15.   SetLength(BlubArray, 2); // Hier wirds lustig
  16. 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.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Aug 07, 2008 12:57 
Offline
DGL Member

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:
  1. var
  2.   array1, array2: array of Blub;
  3.   p1: ^Blub;
  4.  
  5. begin
  6.   SetLength(array1, 1);
  7.   p1 := @array1[0];
  8.   SetLength(array2, 10); //Jetzt ist p1 ungültig
  9. end;


Was Lossy eX mir geraten hat, probiere ich jetzt aus. Schonmal Vielen Dank.

Gruß Joni.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Aug 07, 2008 14:10 
Offline
DGL Member
Benutzeravatar

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:
  1. var
  2.   array1, array2: array of Blub;
  3.   p1: ^Blub;
  4.  
  5. begin
  6.   SetLength(array1, 1);
  7.   p1 := @array1[0];
  8.   SetLength(array2, 10); //Jetzt ist p1 ungültig
  9. 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.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Aug 08, 2008 18:19 
Offline
DGL Member

Registriert: So Okt 21, 2007 14:16
Beiträge: 123
Programmiersprache: Delphi
Hallo,

es funzt jetzt, vielen Dank!

Gruß Joni.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 9 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.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.008s | 15 Queries | GZIP : On ]