type
TTestData=class
x,y :byte
end;
TTest1=class
FList:TList;
constructor Create;
end;
TTest2=class
FTestData:array of array of TTestData;
constructor Create;
end;
end;
constructor TTest1.Create()
var tmp:TTestData
begin
inherited;
FList:=TList.Create;
for i:=0 to 9 do
begin
tmp:=TTestData.Create;
FList.Add(tmp);
end;
end;
constructor TTest2.Create()
begin
inherited;
setlength (FTestData,10,10);
end;
//----------------
procedure MoveData(aValue:TTestData; const hinher:boolean);
begin
if hinher then
begin
Test2.FTestData[aValue.x,aValue.y]:=aValue;
Test1.FList.Delete[Test1.FList.IndexOf(aValue)];
end else
begin
Test1.FList.Add(aValue);
Test2.FTestData[aValue.x,aValue.y]:=nil;
end;
end;
Mal abgesehen davon, dass es eher Pseudocode ist und sicher Tippfehler dabei sind - die Zuweisung eines Objektes aus einer Liste bezieht sich doch nur auf den Zeiger, IMHO. Und wenn ich das Objekt im dynamischen Array auf nil setze, sollte es doch weg sein. Oder? Mein Code funktioniert meistens, aber scheinbar nicht immer - schwer zu debuggen.
TIA, Scotty.
Zuletzt geändert von Scotty am Mi 17. Jun 2009, 17:11, insgesamt 1-mal geändert.
Wenn Du den Zeiger auf das Objekt = NIL setzt, ist es nicht mehr zugreifbar (sofern kein anderer Zeiger darauf existiert). Wenn es den speicher freigeben soll, musst Du Object.Free aufrufen.
Dir Frage ist, ob ich so etwas falsch mache. In einem Testlauf kommt es jedenfalls vor, dass die Felder nicht nil sind, bzw. dass an anderer Stelle etwas unsauber läuft.
Schon klar, dass mein Beispiel sehr vereinfacht ist. Die Eigenschaften wie x und y werden richtig gesetzt.
Wenn ich eine Variable p:Pointer deklariere und mit p:=@data zuweise, dann sind doch, vorausgesetzt alles wird richtig gemacht, in p alle Daten enthalten. Wenn ich p auf nil setze, wird dadurch data zerstört? Ich denke dabei an solche Dinge wie vertauschte Zeilen in meinem Beispiel, d.h. erst Test2.FTestData[aValue.x,aValue.y]:=nil; und dann Test1.FList.Add(aValue);.
Scotty hat geschrieben:Wenn ich eine Variable p:Pointer deklariere und mit p:=@data zuweise, dann sind doch, vorausgesetzt alles wird richtig gemacht, in p alle Daten enthalten. Wenn ich p auf nil setze, wird dadurch data zerstört?
Diese Frage hat mschnell schon beantwortet. P ist nur ein Zeiger auf die Speicherstelle wo das Objekt sitzt.
Du kannst hunderte davon auf ein einziges Objekt zeigen lassen und alle anschliessend Nil setzen, das Objekt (der Speicher) wird dadurch nicht freigegeben, das geht nur mit Obj.free.
Scotty hat geschrieben:Wenn ich eine Variable p:Pointer deklariere und mit p:=@data zuweise, dann sind doch, vorausgesetzt alles wird richtig gemacht, in p alle Daten enthalten.
Scotty hat geschrieben:Wenn ich eine Variable p:Pointer deklariere und mit p:=@data zuweise, dann sind doch, vorausgesetzt alles wird richtig gemacht, in p alle Daten enthalten.
Bitte lies erst 'mal nach, was ein Zeiger ist....
-Michael.
Das lustige ist, dass C++ genau so etwas kann. Also Objekte freigeben, wenn deren Gültigkeit abhanden kommt (geht nur mit automatisch erstellten Objekten). Eine Alternative wäre ein Garbage-Collector. Aber beides gibts nicht in Pascal.
Eine Möglichkeit wäre, die Freigabe der Objekte zu automatisieren:
procedure TSomeClass.SetSomeProperty(AFooValue: TBarObject);
begin
// a ist unser Feld oder Array-Feld oder was weiß ich
if a = AFooValue then exit;
// bei Objekten:
a.Free;
// bei Records:
Dispose(a);
// und neuen Wert (nil) einfügen
a := AFooValue;
end;
Noch ein Tipp: Um zu überprüfen, ob Du alles korrekt freigegeben hast, kannst Du die Unit heaptrc verwenden.
MfG Socke
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Socke hat geschrieben:
Das lustige ist, dass C++ genau so etwas kann. Also Objekte freigeben, wenn deren Gültigkeit abhanden kommt (geht nur mit automatisch erstellten Objekten). ... Aber beides gibts nicht in Pascal.
Mit Interfaces (referenzgezählt) kann Delphi/FPC das auch.
Socke hat geschrieben:
Das lustige ist, dass C++ genau so etwas kann. Also Objekte freigeben, wenn deren Gültigkeit abhanden kommt (geht nur mit automatisch erstellten Objekten). ... Aber beides gibts nicht in Pascal.
Mit Interfaces (referenzgezählt) kann Delphi/FPC das auch.
Bei Delphi-Prism und C# gibt's gar kein free. Da macht das .NET / Mono Framework die Referenz-Überprüfung automatisch. Ich vermute dasselbe gilt für andere Frameworks wie Java und Python genauso.
mschnell hat geschrieben:Bei Delphi-Prism und C# gibt's gar kein free. Da macht das .NET / Mono Framework die Referenz-Überprüfung automatisch.
Bei C# hast du definitiv einen Garbage Collector mit all seinen Vorteilen und Nachteilen. EIner der Vorteile ist, das du dich weniger um Deine Objekte kümmern musst, der Nachteil ist, das du relativ wenig Einfluß hast, wann deine Objekte zerstört werden (man kann es aber kontrollieren). Das kann bei Bildauswertungen im Verbund mit getakteten Maschinen oft sehr störend sein und eine dubiose Quelle von azyklischen Maschinenstops. Im normalen Betrieb überwiegt der Vorteil von dem Automatismus.
Ich liebe an Pascal das Verhalten, das ich mich um meine Objekte kümmern muß, da da das Verhalten sehr vorhersehbar ist.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
af0815 hat geschrieben:Ich liebe an Pascal das Verhalten, das ich mich um meine Objekte kümmern muß, da da das Verhalten sehr vorhersehbar ist.
Der Garbage--Collector kann natürlich riesige Wartezeiten produzieren. Die Philisophie bei .NET ist: wir haben sehr viel RAM und brauchen keine Garbage-Collect zu machen bevor das Programm beendet wird (oder der Rechner abstürzt ).