![]() |
FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Sorry für den blöden Thread-Titel, aber ich kann mir grad nicht helfen.
Ich habe ein Speicherleck, weil ich durch eine Klassenhierarchie eine Bitmap durchreiche, und auf oberster Ebene die Bitmap der Bitmap eines TImage assigne. Jetzt bekomme ich das Leck nicht gestopft, weil die TBitmap.Assign Methode folgendes treibt:
Delphi-Quellcode:
Den in meinen Augen kritischen Abschnitt habe ich kommentiert. Das Problem ist, daß hier ein Assign mit einer Objekt-Zuweisung vermischt wird, und dadurch keine zwei getrennte Objekte entstehen, sondern die sind, eine Ebene tiefer, miteinander verwoben. Falls das so ist, ist das doch Käse. Oder übersehe ich etwas?
procedure TBitmap.Assign(Source: TPersistent);
begin TMonitor.Enter(Self); try if Source = nil then SetSize(0, 0) else if Source is TBitmap then begin DestroyResources; TBitmap(Source).FImage.IncreaseRefCount; // Warum die nächste Zeile? FImage.DecreaseRefCount; // Ab jetzt ist FImage das Fimage Objekt der Source FImage := TBitmap(Source).FImage; BitmapChanged; end else if Source is TBitmapSurface then AssignFromSurface(TBitmapSurface(Source)) else inherited; finally TMonitor.Exit(Self); end; end; Gegenwärtig erzeuge ich massenweise Bitmaps zur Laufzeit, die ich per Assign auf die Oberfläche werfe, und phänotypisch ist alles OK, nur ich verbrate immer mehr Speicher, ohne ihn wirklich freigeben zu können.... Sherlock |
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
BitMaps sind intern referenzgezählt.
Die alte Referenz reduzieren, weil gleich diese Referenz gelöscht/überschrieben wird, mit dem Verweis auf den neuen Inhalt. Darum auch darüber das IncreaseRefCount im anderen Bitmap, da hier gleiche eine Referenz auf dessen Inhalt gespeichert wird. Hier eben alles manuell und keine autoamtische Referenzzählung. (Interface oder ARC) So lange beide Bitmaps nichts an ihrem Inhalt ändern, verweisen sie auf den selben Inhalt und sparen so Speicher. Bei Änderungen sollte dann wohl irgendwo der Inhalt kopiert und mit einer "echten" Kopie weitergearbeitet werden. |
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Das ist nicht wirklich befriedigend. Mein Problem ist zB folgendes (ich habe mehrere Bitmap Lecks, aber das hier ist sehr einfach erklärt):
Ich zeichne ein recht umfangreiches Koordinatengitter mit wiederholenden Spines. Das dauert je nach Rechner seine Zeit, weshalb ich es einfach nach Erzeugung abspeichere und dann immer wieder bei Bedarf per TBitmap.CreateFromFile lade. Dieses Objekt Assigne ich einem TImage, daß auf meiner Form liegt. Das Koordinatengitter wird auflösungsabhängig erzeugt/gespeichert/geladen. Wenn die Fenstergröße geändert wird, werden anders skalierte Gitter benötigt, und die alten weggeworfen. Weil ich bisher nicht wirklich wegwarf, sondern "drüber assignte" hab ich also ein Speicherleck. Jetzt wollte ich die alte Bitmap des TImages wegwerfen, aber das geht ja gar nicht. Was tun? Sherlock |
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Zitat:
|
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Ich habe die ganz dufte CopyFromBitmap Methode entdeckt. Damit hat sich der Spuk für mich erledigt. Ich setze die Größe meines Ziels auf die Größe der Quelle und dann führe ich TBitmap.CopyFromBitmap(Source) aus und fertig. Kein Speicherleck mehr.
Wenn ich dann mal Zeit habe, schaue ich mir vielleicht an, was beim Assign falsch laufen könnte, aber jetzt bin ich glücklich. :) Danke Himitsu, es hilft häufig einfach nur über ein Problem zu reden. Sherlock |
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Ein Speicherleck oder Bug ist mir an der Stelle nicht bekannt und es funktioniert so wie es soll.
Weder hier
Delphi-Quellcode:
noch da
var
bmp: TBitmap; begin bmp := TBitmap.CreateFromFile('picture.png'); try Image1.Bitmap := bmp; finally bmp.Free(); end; end;
Delphi-Quellcode:
passiert etwas Merkwürdiges.
var
bmp: TBitmap; begin bmp := TBitmap.CreateFromFile('picture.png'); try Image1.Bitmap.Assign(bmp); finally bmp.Free(); end; end; Interessant wäre zu sehen, was du in deinem Code konkret veranstaltest ... |
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Delphi-Quellcode:
und
Image1.Bitmap := bmp;
Delphi-Quellcode:
ist das Selbe, siehe dem Setter von .Bitmap
Image1.Bitmap.Assign(bmp);
[edit] OK, bei Startet nicht, aber glaub mir einfach, dass der Setter intern das Assign aufruft. :angle: |
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Vor allem wäre die Plattform interessant (also mit ARC oder ohne). 8-)
|
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Tja, mein Code reicht durch mehrere Ebenen und in mehrere Listen. Ich war überzeugt, alles wird gut aufgeräumt. Und dadurch, daß ich nicht mehr Assign sondern CopyFromBitmap verwende werden mir auch keine Leaks mehr gemeldet. Eventuell habe ich auch einfach nur den Überblick verloren... Dennoch sehen meine eigenen Assign-Methoden anders aus, als das da. Für mich besteht ein Assign darin, zwei vollständig unabhängige Objekte gleichen Inhalts zu erzeugen...Klonen sozusagen. Und das passiert da IMHO nicht. Und den Inhalt eines Objekts zu setzen, daß in der nächsten Zeile durch ein anderes ersetzt wird, finde ich auch komisch.
Sherlock |
AW: FMX: TBitmap.Assign Methode erscheint mir nicht korrekt
Du meinst dein Assign sieht ungefähr so aus?
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE} {$R *.res} uses System.Classes, System.SysUtils; type TMyClass = class( TPersistent ) private FData: string; public procedure Assign( Source: TPersistent ); override; public property Data: string read FData write FData; end; procedure TMyClass.Assign( Source: TPersistent ); begin if ( Source is TMyClass ) then begin FData := TMyClass( Source ).FData; end else inherited; end; var a, b: TMyClass; begin try a := nil; b := nil; try a := TMyClass.Create(); b := TMyClass.Create(); a.Data := 'Foo'; b.Assign(a); WriteLn(b.Data); finally a.Free; b.Free; end; except on E: Exception do Writeln( E.ClassName, ': ', E.Message ); end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:54 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz