Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   FreePascal (https://www.delphipraxis.net/74-freepascal/)
-   -   specialize TFPGObjectList : AV bei Free (https://www.delphipraxis.net/188745-specialize-tfpgobjectlist-av-bei-free.html)

Alter Mann 2. Apr 2016 17:33

specialize TFPGObjectList : AV bei Free
 
Hallo,

da das mit den Rescourcen klappt, kommt das nächste Problemchen mit specialize TFPGObjectList:|
Folgendes ist gegeben
Code:
type
  TSmileyInfo = record
    Character : Integer;
    Resource : Integer;
  end;

  TSmiley  = class(TObject)
  private
    FCharacter : Integer;
    FImage    : TPicture;
  public
    constructor Create(aCharacter : Integer; aImage : TPicture);
    destructor Destroy; override;

    procedure render(deviceContext : HDC; X, Y : Integer);
    property Character : Integer read FCharacter;
  end;

  Smileys      = specialize TFPGObjectList<TSmiley>;

  TSmileys     = class(TObject)
  private
    FSmileys   : Smileys;
  protected
    procedure Load(aSmileyInfo : TSmileyInfo);
    function Find(aCharacter : Integer): TSmiley;
  public
    constructor Create;
    destructor Destroy; override;
    procedure  renderSmiley(aCharacter : Integer; deviceContext : HDC; X, Y : Integer);
  end;
In TSmileys.FSmileys werden 845 Smileys geladen:
Code:
...
constructor TSmileys.Create;
var
  I : Integer;
begin
  inherited Create;
  FSmileys := Smileys.Create(True);

  for I := Low(TSmileyList) to High(TSmileyList) do
    Load(TSmileyList[I]);
end;

procedure  TSmileys.Load(aSmileyInfo : TSmileyInfo);
begin
  FSmileys.Add(TSmiley.Create(aSmileyInfo.Character,
    ResourceLoader.loadImageFromResource(aSmileyInfo.Resource, itPNG)));
end;
...
Das Problem taucht nun beim freigeben auf, egal wie ich es mache, es kommt zu einer AV:(
Code:
...
constructor TSmiley.Create(aCharacter : Integer; aImage : TPicture);
begin
  inherited Create;
  FCharacter := aCharacter;
  FImage    := aImage;
end;

destructor TSmiley.Destroy;
begin
  if Assigned(FImage) then
    FImage.Free;              <- Hier
  inherited Destroy;
end;
...
destructor TSmileys.Destroy;
var
  Smiley : TSmiley;
begin
  for Smiley in FSmileys do
    if Assigned(Smiley) then
       Smiley.Free;

  FSmileys.Free;
  inherited Destroy;
end;
...
Das blöde ist nur das es immer bei einem anderen Picture kommt.

Wie kann ich das Image(TPicture) freigeben ohne das Knallt?
FreeAndNil geht auch nicht.

mjustin 2. Apr 2016 17:57

AW: specialize TFPGObjectList : AV bei Free
 
Zitat:

Zitat von Alter Mann (Beitrag 1334518)
Wie kann ich das Image(TPicture) freigeben ohne das Knallt?

Besteht das Problem auch, wenn anstatt eines TImage eine andere Klasse, die weniger 'sensibel' ist (also zumBeispiel TStringList, TButton, ...) als Typ der Property TSmiley.FImage verwendet wird?

Zacherl 2. Apr 2016 18:11

AW: specialize TFPGObjectList : AV bei Free
 
Ich sehe, dass die Referenz auf
Delphi-Quellcode:
FImage
im Constructor reingegeben - und nicht intern erzeugt wird. Vermutlich wird die Instanz durch irgendeinen Logikfehler deshalb mehrfach freigegeben.

Alter Mann 2. Apr 2016 19:09

AW: specialize TFPGObjectList : AV bei Free
 
@Zacherl

Ich werde morgen mal FImage initialisieren und das übergebene Picture via Assing zuweisen,
mal sehen vielleicht geht das ja.

Danke erstmal und noch einen schönen Abend:wink:

Update:

Also eine Änderung in:
Code:
constructor TSmiley.Create(aCharacter : Integer; aImage : TPicture);
begin
  inherited Create;
  FCharacter := aCharacter;
  FImage    := TPicture.Create;
  FImage.Assign(aImage);
end;
bringt auch nichts :o.

haentschman 3. Apr 2016 06:35

AW: specialize TFPGObjectList : AV bei Free
 
Moin...:P

Du erzeugst die Objektliste mit OwnsObjects = True und gibst im destructor selbst die enthaltenen Bilder wieder frei. Das muß Puff machen...:wink: Wenn du die Instanzen selbst verwalten möchtest dann OwnsObjects auf False. Dann würde das mit der Freigabe passen. Dann brauchst du aber auch nicht auf Assigned prüfen. Jeder Listeneintrag ist ein Pointer.
Delphi-Quellcode:
FSmileys := Smileys.Create(True); // OwnsObjects = True
.
.
.
destructor TSmileys.Destroy;
var
  Smiley : TSmiley;
begin
//  for Smiley in FSmileys do // diesen Block brauchst du nicht
//    if Assigned(Smiley) then
//       Smiley.Free; //

  FSmileys.Free;
  inherited Destroy;
end;
..fertsch. :zwinker:

Alter Mann 3. Apr 2016 08:00

AW: specialize TFPGObjectList : AV bei Free
 
Ja, sieht ganz so aus:oops:.

Ich habe es jetzt so gemacht und es geht:wink:
Code:
...
destructor TSmiley.Destroy;
begin
  FPicture.Free;
  inherited Destroy;
end;
...
destructor TSmileys.Destroy;
begin
  FSmileys.Clear;
  FSmileys.Free;
  inherited Destroy;
end;
Danke

haentschman 3. Apr 2016 10:54

AW: specialize TFPGObjectList : AV bei Free
 
Siehst du... again what learned. :stupid:

Das
Delphi-Quellcode:
FSmileys.Clear;
kannst du auch weglassen. Das wird beim Free automatisch gemacht. Um Daniel zu zitieren: "Verschwendung von wertvollen Bits und Bytes" 8-)

DeddyH 3. Apr 2016 11:51

AW: specialize TFPGObjectList : AV bei Free
 
Und es geht noch kürzer:
Delphi-Quellcode:
destructor TSmileys.Destroy;
begin
  FSmileys.Free;
  inherited;
end;
Da der Destruktor dieselbe Signatur hat wie der geerbte, kann der explizite Aufruf entfallen.

haentschman 3. Apr 2016 13:45

AW: specialize TFPGObjectList : AV bei Free
 
...den hatte ich gar nicht gesehen weil selbstverfreilich. :oops:


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:23 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