Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Bitmap.Free und TObjectList (https://www.delphipraxis.net/184348-bitmap-free-und-tobjectlist.html)

amigage 19. Mär 2015 11:26

Delphi-Version: XE7

Bitmap.Free und TObjectList
 
Hallo liebe Delphianer,

ich bräuchte einmal eine verständliche, theoretische Erklärung für mein Problem.
und zwar wirkt sich bei mir ein Bitmap.Free auf den Inhalt meiner TObjectList aus...

Delphi-Quellcode:
  TMyEntry = class(TObject)
// ...
    Icon : TBitmap;
// ...
  end;
  TMyEntryList = TObjectList<TMyEntry>;
Delphi-Quellcode:
MyList := TObjectList<TMyEntry>;


Und hier der Quellcode zu meinem Problem.

Delphi-Quellcode:
var
  i : integer;
  MyEntry : TMyEntry;
  AIcon : TBitmap;
begin

AIcon := TBitmap.Create;
AIcon.PixelFormat := pf32Bit;

for i := 0 to MyList.Count - 1 do
   begin
       MyEntry := TMyEntry(MyList[I]);
       If MyEntry.Icon = NIL then
       begin
         try
           ImageList.GetBitmap(1, AIcon);
         except
         end;
       end
       else
       begin
         AIcon := MyEntry.Icon;
       end;
       // weitere Verwendung von AIcon
end;
Folgender Durchlauf:
1) MyEntry.Icon <> NIL, also AIcon = MyEntry.Icon
2) MyEntry.Icon = NIL, also AIcon aus einer ImageList holen

Problem: bei Durchlauf 2 wird das AIcon und damit mein MyEntry.Icon überschrieben

Also ein anderer Versuch, das AIcon immer neu zu erstellen.

Delphi-Quellcode:
var
  i : integer;
  MyEntry : TMyEntry;
  AIcon : TBitmap;
begin
for i := 0 to MyList.Count - 1 do
   begin
     AIcon := TBitmap.Create;
     AIcon.PixelFormat := pf32Bit;
     try
       MyEntry := TMyEntry(MyList[I]);
       If MyEntry.Icon = NIL then
       begin
         try
           ImageList.GetBitmap(1, AIcon);
         except
         end;
       end
       else
       begin
         AIcon := MyEntry.Icon;
       end;
       // weitere Verwendung von AIcon
     finally
        AIcon.Free;
     end;
end;
Gleicher Durchlauf:
Problem: durch AIcon.Free wird ebenfalls MyEntry.Icon gelöscht -> Zugriffsverletzung beim Aufruf

Kann mir bitte jemand erklären, warum AIcon noch eine Beziehung zu MyEntry.Icon hat?
Wie muss ich MyEntry.Icon an AIcon übergeben, damit ich AIcon ordnungsgemäß löschen kann, ohne MyEntry.Icon zu löschen?
Aktuell muss ich AIcon.Free auskommentiert lassen....

Vielen Dank schon einmal, an diejenigen, die mir dies erklären können.

_

Zacherl 19. Mär 2015 11:46

AW: Bitmap.Free und TObjectList
 
Zitat:

Zitat von amigage (Beitrag 1294057)
Kann mir bitte jemand erklären, warum AIcon noch eine Beziehung zu MyEntry.Icon hat?

Bei der Zuweisung zweier Objekte mit dem Zuweisungsoperator wird lediglich die Referenz (Zeiger) zugewiesen. Das Bedeutet, dass in deinem Falle Entry.MyIcon und AIcon auf die selbe Objektinstanz zeigen.
Gibst du jetzt die Objektinstanz frei, sind logischerweise beide Referenzen ungültig.

Zitat:

Zitat von amigage (Beitrag 1294057)
Wie muss ich MyEntry.Icon an AIcon übergeben, damit ich AIcon ordnungsgemäß löschen kann, ohne MyEntry.Icon zu löschen?

Du solltest statt
Delphi-Quellcode:
AIcon := MyEntry.Icon
lieber
Delphi-Quellcode:
AIcon.Assign(MyEntry.Icon)
verwenden, um den Inhalt des Icons zu kopieren.

Bzw. macht das ständige Erstellen und Freigeben des Icons auch gar keinen Sinn. So wie ich deinen Code verstehe, willst du die Icons doch grade für spätere Verwendung in der MyList zwischenspeichern. Probiers mal so:
Delphi-Quellcode:
var
  I: Integer;
  MyEntry: TMyEntry;
  Icon: TBitmap;
begin
  for := MyList.Count - 1 do
  begin
    MyEntry := TMyEntry(MyList[I]);
    if (not Assigned(MyEntry.Icon)) then
    begin
      Icon := TBitmap.Create;
      Icon.PixelFormat := pf32Bit;
      ImageList.GetBitmap(1, Icon);
      MyEntry.Icon := Icon;
    end else
    begin
      Icon := MyEntry.Icon;
    end;
    // weitere Verwendung von Icon
  end;
end;
Freigeben musst du die Icons dann, wenn du sie nicht mehr brauchst, indem du MyList nochmal iterierst und alle nicht leeren Bitmaps zerstörst.
Delphi-Quellcode:
var
  I: Integer;
  MyEntry: TMyEntry;
begin
  for := MyList.Count - 1 do
  begin
    MyEntry := TMyEntry(MyList[I]);
    if (Assigned(MyEntry.Icon)) then
    begin
      FreeAndNil(MyEntry.Icon);
    end;
  end;
end;

Klaus01 19. Mär 2015 11:48

AW: Bitmap.Free und TObjectList
 
Hallo,

mit AIcon := MyEntry.Icon; weist Du AIcon die selbe Adresse wie MyEntry.Icon zu.

Wenn Du den Inhalt von MyEntry.Icon nach AIcon kopieren möchtest,
dann solltest Du assign verwenden.

Grüße
Klaus

Blup 19. Mär 2015 12:07

AW: Bitmap.Free und TObjectList
 
Willst du tatsächlich mit einer Kopie des Icons arbeiten, dann so:
Delphi-Quellcode:
AIcon.Assign(MyEntry.Icon);
AIcon.PixelFormat := pf32Bit;
{...}

himitsu 19. Mär 2015 12:29

AW: Bitmap.Free und TObjectList
 
PS: Du verwendest doch eine generische Liste, welche automatisch den richtigen Typen besitzt,
demnach sind die manuellen Casts ein bissl "überflüssig".

Zitat:

Delphi-Quellcode:
TMyEntry(MyList[I]);

Entweder nur den Cast weglassen, oder einfach die klomplette
Delphi-Quellcode:
MyEntry
-Variable entfernen und überall direkt
Delphi-Quellcode:
MyList[I]
verwenden, anstatt der Variable.

amigage 19. Mär 2015 13:31

AW: Bitmap.Free und TObjectList
 
An alle,

vielen, vielen Dank für die Erklärungen. Ich habe mir schon gedacht, dass beide auf das Gleiche verweisen.
Ich wusste jedoch nicht, wie ich eine tatsächliche Kopie übergebe. Jetzt weiß ich es :-D

@himitsu: danke für den Hinweis auf den überflüssigen Cast.


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