AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TPngImage freigeben

Ein Thema von amigage · begonnen am 20. Aug 2020 · letzter Beitrag vom 20. Aug 2020
Antwort Antwort
amigage

Registriert seit: 11. Nov 2005
Ort: Leipzig
272 Beiträge
 
Delphi 11 Alexandria
 
#1

TPngImage freigeben

  Alt 20. Aug 2020, 12:41
Delphi-Version: 10.4 Sydney
Hallo,

ich bin gerade dabei, die MemLeaks aus meinem Programm zu entfernen. Ein Problem habe ich hierbei:
Ich lade, je nach Bildschirmauflösung, verschieden große Grafiken über ein Funktion.

Delphi-Quellcode:
ImageMain.Picture.Graphic := StartDlg.LoadImgFromResource('Main');

function TStartDlg.LoadImgFromResource(Bezeichner: String): TPngImage;
var
  Png: TPngImage;
begin
  Result := NIL;

  Png := TPngImage.Create;
  try
   // DPI 200%
   if Screen.PixelsPerInch >= 192 then
     Png.LoadFromResourceName(HInstance, Bezeichner + '_200')
   // DPI 150%
   else if Screen.PixelsPerInch >= 144 then
     Png.LoadFromResourceName(HInstance, Bezeichner + '_150')
   // DPI 100%
   else
     Png.LoadFromResourceName(HInstance, Bezeichner + '_100');

    Result := Png;
  finally
// Png.Free; // kann ich hier nicht freigeben
  end;
end;
Beim Beenden wird mir ein TPngImage und TPngImageList Memory Leak ausgegeben. Wie kann ich das am Ende freigeben? Muss ich die Grafik dem TImage anders übergeben, damit ich das TPngImage in der Funktion freigeben kann?

Danke, für einen Hinweis.

Geändert von amigage (20. Aug 2020 um 12:43 Uhr) Grund: Falsche Angabe der Delphi Version
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.195 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: TPngImage freigeben

  Alt 20. Aug 2020, 12:48
Entweder übergibst du ein TPNGImage an die Funktion.
Dann brauchst du keines Freigeben.

Oder die Methode erzeugt es und übergibt es. Dann ist der Aufrufer dafür zuständig.

Was wird denn mit dem PNG gemacht? Evtl. an ein TImage gehängt?
Dann solltest du das TImage als Parameter übergeben.
Den beim Zuordnen an das TImage wird eine Kopie des TPNGImage erstellt.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: TPngImage freigeben

  Alt 20. Aug 2020, 12:52
Hallo,
pack das TPngImage doch als private Variable in dein TStartDlg.
So wie du das hier erzeugst, sollte der Start-Dialog das dann selber freigeben.
Heiko
  Mit Zitat antworten Zitat
amigage

Registriert seit: 11. Nov 2005
Ort: Leipzig
272 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: TPngImage freigeben

  Alt 20. Aug 2020, 14:15
Danke, ich habe mit für Bernhards Variante entschieden, da noch weitere Formulare auf die Funktion zugreifen.

Dann solltest du das TImage als Parameter übergeben.
Den beim Zuordnen an das TImage wird eine Kopie des TPNGImage erstellt.
Der Tipp war Gold wert. Danke 👌
Delphi-Quellcode:
StartDlg.LoadImgFromResource('Main', ImageMain);

procedure TStartDlg.LoadImgFromResource(Bezeichner: String; MyImage : TImage);
var
  Png: TPngImage;
begin
  Png := TPngImage.Create;
  try
   // DPI 200%
   if Screen.PixelsPerInch >= 192 then
     Png.LoadFromResourceName(HInstance, Bezeichner + '_200')
   // DPI 150%
   else if Screen.PixelsPerInch >= 144 then
     Png.LoadFromResourceName(HInstance, Bezeichner + '_150')
   // DPI 100%
   else
     Png.LoadFromResourceName(HInstance, Bezeichner + '_100');

    MyImage.Picture.Graphic := Png;
  finally
    Png.Free;
  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.387 Beiträge
 
Delphi 12 Athens
 
#5

AW: TPngImage freigeben

  Alt 20. Aug 2020, 14:31
Moin...
https://www.detlef-heibing.de/progra...rueckgabe.html
Prinzipiell kann man sowas machen...der constructor ist ja auch nix anderes. Aber der Name der function sollte beinhalten, daß ein object erzeugt wird!
Delphi-Quellcode:
function TStartDlg.LoadImgFromResource(Bezeichner: String): TPngImage;
...
function TStartDlg.CreateImgFromResource(Bezeichner: string): TPngImage;
...dann weiß man, daß man sich selbst um die Freigabe kümmern muß. Persönlich bekomme ich u.a. die Objekte aus der DB und packe sie in eine Liste. Die Liste übernimmt dann die Freigabe.

Geändert von haentschman (20. Aug 2020 um 14:56 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#6

AW: TPngImage freigeben

  Alt 20. Aug 2020, 18:21
Besser den kleinsten gemeinsammen Nenner verwenden, also statt TImage das TPicture.
(Igentlich wäre das Kleineste TGraphic, aber für diesen Aufruf geht es nur bis TPicture)
Delphi-Quellcode:
StartDlg.LoadImgFromResource('Main', ImageMain.Picture);

procedure TStartDlg.LoadImgFromResource(Bezeichner: String; Image: TPicture);
So kann man die Funktion auch zum internen Laden benutzen, wo man keine große/sichtbare Komponente nutzen möchte.


Auch wenn nicht mehr nötig, nochmal als Erklärung:


Joar, da hier bei der Zuweisung nur den Inhalt des Objektes kopiert und nicht das Objekt übergeben/freigibt wird, mußt du das Result der Funktion am Ende freigeben.

Und wie haentschman bereits sagte, sollte man den Namen der Funktion anfassen, um das Verhalten auch gleich mit zu dokumentieren. (Create statt Load oder CreateAndLoadImageFormResource)

Delphi-Quellcode:
Image := StartDlg.CreateImgFromResource('Main');
try
  ImageMain.Picture.Graphic := Image; // entspricht ja eigentlich einem ImageMain.Picture.Graphic.Assign(Image);
finally
  Image.Free;
end;

function TStartDlg.CreateImgFromResource(Bezeichner: String): TPngImage;
begin
  Result := TPngImage.Create;
  try
    if Screen.PixelsPerInch >= 192 then
      Result.LoadFromResourceName(HInstance, Bezeichner + '_200') // DPI 200%
    else if Screen.PixelsPerInch >= 144 then
      Result.LoadFromResourceName(HInstance, Bezeichner + '_150') // DPI 150%
    else
      Result.LoadFromResourceName(HInstance, Bezeichner + '_100'); // DPI 100%
  except
    Result.Free; // wenn es beim Laden knallte, muß es hier schon freigegeben werden, da Result nicht aus fer Funktion raus kommt
    raise;
  end;
end;
Oder als Parameter: Objekt extern erstellen und dort freigeben.
Delphi-Quellcode:
Image := TPngImage.Create;
try
  LoadImgFromResource('Main', Image);
  ImageMain.Picture.Graphic := Image;
finally
  Image.Free;
end;

procedure TStartDlg.LoadImgFromResource(Bezeichner: String; Image: TPngImage);
begin
  if Screen.PixelsPerInch >= 192 then
    Image.LoadFromResourceName(HInstance, Bezeichner + '_200') // DPI 200%
  else if Screen.PixelsPerInch >= 144 then
    Image.LoadFromResourceName(HInstance, Bezeichner + '_150') // DPI 150%
  else
    Image.LoadFromResourceName(HInstance, Bezeichner + '_100'); // DPI 100%
end;

Entspricht deiner letzten Variante, außer
* TPicture statt TImage übergeben
* die Instanz wird nur erzeugt, wenn noch kein PNG vorhanden ist
* die Behandlung des Namen vom dem Ladeaufruf entkoppelt
Delphi-Quellcode:
LoadImgFromResource('Main', ImageMain.Picture);

function TStartDlg.LoadImgFromResource(Bezeichner: String; Picture: TPicture);
var
  Temp: TPngImage;
begin
  if Screen.PixelsPerInch >= 192 then
    Bezeichner := Bezeichner + '_200'   // DPI 200%
  else if Screen.PixelsPerInch >= 144 then
    Bezeichner := Bezeichner + '_150'   // DPI 150%
  else
    Bezeichner := Bezeichner + '_100'; // DPI 100%

  if not (Picture.Graphic is TPngImage) then begin // wenn TPngImage schon drin ist, muß man es nicht nochmal neu erzeugen
    Temp := TPngImage.Create;
    try
      Picture.Graphic := Temp; // ja, die Behandlung von Graphic ist echt krank, aber das liegt nicht an dir
    finally
      Temp.Free;
    end;
  end;

  //Picture.Graphic.LoadFromResourceName(HInstance, Bezeichner);
  TPngImage(Picture.Graphic).LoadFromResourceName(HInstance, Bezeichner); // vermutlich geht es auch direkt und wird durchgereicht, aber ich war mir grad nicht ganz sicher
end;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort


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 04:46 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