AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Objekt in Array kopieren und anschließend freigeben
Thema durchsuchen
Ansicht
Themen-Optionen

Objekt in Array kopieren und anschließend freigeben

Ein Thema von blackdrake · begonnen am 30. Aug 2008 · letzter Beitrag vom 1. Sep 2008
Antwort Antwort
Seite 1 von 3  1 23      
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#1

Objekt in Array kopieren und anschließend freigeben

  Alt 30. Aug 2008, 20:45
Hallo.

Ich habe in einem Projekt Records in Klassen umgewandelt, da ich von diesen nun ableiten kann. Seit dem erhalte ich eine AV.

Hier erstmal der vereinfachte Code zur Reproduktion:

Delphi-Quellcode:
type
  // Anmerkung: War mal ein record, andere Klassen leiten aber jetzt hiervon ab
  TSubmission = class
    Tags: string;
    Rating: string;
    Score: integer;
    PictureNumber: integer;
    MD5: string;
  end;

  TSubmissionArray = array of TSubmission;

procedure AddToArray(var SubmissionArray: TSubmissionArray; const Value: TSubmission);
var
  l: integer;
begin
  l := Length(SubmissionArray);
  SetLength(SubmissionArray, l + 1);
  SubmissionArray[l] := Value;
end;

function Collect: TSubmissionArray;
var
  i: integer;
  Submission: TSubmission;
  tmp: TSubmissionArray;
begin
  for i := 0 to 10 do
  begin
    Submission := TSubmission.Create;
    try
      Submission.MD5 := 'test'+IntToStr(i);

      AddToArray(tmp, Submission);
    finally
      Submission.Free; // PROBLEM!
    end;
  end;

  showmessage(tmp[2].MD5); // Leer, durch Free()

  result := tmp;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  x: TSubmissionArray;
begin
  x := Collect;

  showmessage(x[2].MD5); // Leer, durch Free();
  // In einem anderen Projekt sogar eine AccessViolation bei ntdll.dll
end;
Submission ist ein Objekt vom Typ TSubmission und wird 10 Mal dynamisch erstellt und mit Werten belegt. Anschließend möchte ich die Submission in einen SubmissionArray hängen (siehe AddToArray).

Anschließend gebe ich Submission frei. Und dies verursacht bei mir eine AV bei allen zukünftigen Zugriffen auf die Array-Elemente und deren Eigenschaften.

Kommentiere ich die Zeile "Submission.Free" aus, funktioniert alles. Dies erachte ich jedoch als ein Problem, da der Speicher nicht freigegeben wird.

Was passiert hier? Wieso wird in der Funktion AddToArray() keine Kopie der TSubmission-Instanz gemacht, die in den Array wandert? Wieso gehen die Array-Elemente kaputt, wenn ich das Originalstück freigebe?

Bei Strings, die als Variable in eine Funktion wandern, kenne ich die Routine UniqueString(). Hier muss ich mein TSubmission irgendwie auch "einzigartig" machen, oder?

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 30. Aug 2008, 20:48
Im Array legst du ja nur Referenzen auf die Objekte ab. Wenn du diese dann freigibst, zeigen diese ins Leere
Markus Kinzler
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#3

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 30. Aug 2008, 20:51
Soll ich dann auf den Ressourcenschutzblock verzichten? Wer kümmert sich dann um die Speicherfreigabe?
Daniel Marschall
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 30. Aug 2008, 20:52
Du selber mit dem .Free()
Markus Kinzler
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#5

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 30. Aug 2008, 21:09
Meinst du etwa so?

1. Ich entferne den Ressourcenschutzblock (Free) in der Funktion "Collect".

2. Ich gebe alle Arrayelemente in meinem Button OnClick nacheinander frei

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  x: TSubmissionArray;
  i: integer;
begin
  x := Collect;

  showmessage(x[2].MD5);

  // Array und seine Elemente werden ab hier nicht mehr gebraucht
  for i := 0 to high(x) do
  begin
    x[i].Free;
  end;
end;
Ist das sinnvoll? Eigentlich habe ich mir angewöhnt, überall einen Ressourcenschutzblock sofort einzubauen, nachdem man etwas mit Create() erstellt hat.

Die dieser Lösung jetzt dürfte man das Freigeben in der For-Schleife niemals vergessen, wenn man mit einem TSubmissionArray arbeitet, oder?

Gedankengang A:

Das TSubmissionArray "x" ist als Variable innerhalb von Button1Click deklartiert. Muss man die einzelnen Elemente überhaupt explizit freigeben? Oder wird dies automatisch gemacht, da der Array automatisch freigegeben wird (Ich glaube nicht, da er nur Referenzen enthält).

Gedankengang B:

Wäre es nicht besser, wenn ich in AddToArray() das TSubmission-Objekt irgendwie verdoppeln (einzigartig machen) könnte? Dann könnte ich meinen Ressourcenschutzblock behalten und müsste mich nicht um das Freigeben in einer For-Schleife kümmern. Nur wie macht man das?

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 30. Aug 2008, 21:15
Wenn du diese in eine Objektliste steckst, kannst du auf das manuelle Freigeben verzichten, bei einem Array nicht
Markus Kinzler
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#7

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 30. Aug 2008, 23:24
Hallo.

Wenn ein Array immer eine separate Freigabe benötigt, dann brauche ich ja den Ressourcenschutzblock in meiner Prozedur, die den Array mit Elementen befüllt, nicht mehr.

Ich habe jetzt das Freigeben der Arrayelemente ("Freigeben des Arrays") noch ausgelagert:

Delphi-Quellcode:
procedure FreeSubmissionArray(SubmissionArray: TSubmissionArray);
var
  i: integer;
begin
  for i := 0 to High(SubmissionArray) do
  begin
    SubmissionArray[i].Free;
  end;
end;
Diese Prozedur führe ich nun aus, wenn ich den Array nicht mehr brauche. Zu Memory-Leaks kommt es nicht.

Ist das jetzt eine Variante, wie sie auch professionell gemacht werden würde, oder ist das, was ich hier mache, in irgend einer Weise ungünstig? Es ist eben irgendwie für mich von Nachteil, da ich nun bei den TSubmissionArrays niemals FreeSubmissionArray() vergessen darf.

Ich hatte auch noch mal probiert, die Funktion AddToArray so zu modifizieren, dass das Objekt vor dem Hinzufügen zum Array kopiert wird. Ist leider fehlgeschlagen:

Delphi-Quellcode:
procedure AddToArray(var SubmissionArray: TSubmissionArray; const Value: TSubmission);
var
  l: integer;
begin
  l := Length(SubmissionArray);
  SetLength(SubmissionArray, l + 1);
  SubmissionArray[l] := TSubmission(Value.NewInstance); // Kopieren? Eher nicht...
end;
Entschuldige bitte mein Unwissen, aber was ist eine "Objektliste"? Diesen Ausdruck habe ich noch nicht gehört. Auch Google sagt mir jetzt nicht wirklich eine Definition von dem Begriff.

Darf ich eine kleine Frage am Rande stellen?

Eine überladene Funktion von AddToArray arbeitet mit Strings:

Delphi-Quellcode:
type
  TStringArray: array of String;

procedure AddToArray(var StringArray: TStringArray; const Value: string);
var
  l: integer;
begin
  l := Length(StringArray);
  SetLength(StringArray, l + 1);
  StringArray[l] := Value;
end;
Muss ich hier mit UniqueString() arbeiten, oder wird hier der String tatsächlich in den Array kopiert? Wenn nicht, dann würde sich doch der Array ändern, wenn ich den String, den ich AddToArray() gegeben habe, ändere, oder?

Gruß
blackdrake
Daniel Marschall
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 31. Aug 2008, 01:09
Zitat von blackdrake:
Ist das jetzt eine Variante, wie sie auch professionell gemacht werden würde, oder ist das, was ich hier mache, in irgend einer Weise ungünstig?
Nain, da sist schon richtig so.

Zitat:
Es ist eben irgendwie für mich von Nachteil, da ich nun bei den TSubmissionArrays niemals FreeSubmissionArray() vergessen darf.
Deswegen nimmt man eine Objektliste. Diese kann sich entweder selber umm das Freigeben kümmern oder man überschreibt den Destruktor und gibt dort die Objekte in der Liste "von Hand" frei.

Dein Array ist wieder nur so eine halbherzige Umsetzung des OOP Gedankens.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
grenzgaenger
(Gast)

n/a Beiträge
 
#9

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 31. Aug 2008, 01:14
Zitat von blackdrake:
Entschuldige bitte mein Unwissen, aber was ist eine "Objektliste"? Diesen Ausdruck habe ich noch nicht gehört. Auch Google sagt mir jetzt nicht wirklich eine Definition von dem Begriff.
Delphi-Referenz durchsuchenTObjectList definiert in der unit contrns (oder so ähnlich)
  Mit Zitat antworten Zitat
blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#10

Re: Objekt in Array kopieren und anschließend freigeben

  Alt 31. Aug 2008, 01:15
Zitat von Luckie:
Deswegen nimmt man eine Objektliste. Diese kann sich entweder selber umm das Freigeben kümmern oder man überschreibt den Destruktor und gibt dort die Objekte in der Liste "von Hand" frei.
Kann ich aus dem Zitat schließen: Objektliste = Klasse?

Zitat von Luckie:
Dein Array ist wieder nur so eine halbherzige Umsetzung des OOP Gedankens.
Was sollte man/ich anstelle eines Arrays nutzen? Es gibt eine ungewisse Anzahl von TSubmission's, da ist doch ein dyn. Array die beste Lösung, oder?

Zitat von grenzgaenger:
TObjectList definiert in der unit contrns (oder so ähnlich)
Ok, ich Probiere mal etwas mit der TObjectList zu machen
Daniel Marschall
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz