Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi speicher wächst und wächst bei TBitmap Appl (https://www.delphipraxis.net/127949-speicher-waechst-und-waechst-bei-tbitmap-appl.html)

Hoelderlein 21. Jan 2009 20:51


speicher wächst und wächst bei TBitmap Appl
 
Hallo erstmal,

bin neu hier, hab kein Platz zum vorstellen gefunden also Hallo an alle.

Vorab, bin kein Programmierprofi in Delphi, komm ganz gut zurecht mach aber scheinbar ab und zu noch drastische Fehler. Von Haus aus programmier ich eher SPS und industrielle Kamerasysteme.

Nun zum Thema:

Hab vor 1,5 Jahren ein Projekt in Delphi ohne Vorkenntnisse angefangen. Hab jetzt ein Programm bei dem ich 60 Fotos von einem sich drehendem Objekt mache. Diese in meine Software integriere und per scrollbar das Objekt in 60 Schritten um die eigene Achse drehen lassen kann. Ich kann bis zu 30 Objekte in die Software einbinden.

Hab in der Signatur die Add. zur UNKOMMERZIELLEN Homepage

Also viel viel Bilder in JPG. Hatte eigentlich gedacht ich bin zu 99% fertig. Jetzt stell ich fest das ich ein riesen Speicherproblem hab.

Hab mich mal mittels suche schlau gemacht und gelernt das es z.B. free gibt und z.B. das lokale Variablen keinen Speicherplatz mehr beanspruchen wenn z.B. die Prozedur beendet wird.

Hätt ich mich besser mal vorher schlau gemacht.

Hab also ein TImage in dem Angezeigt wird und je nach Schiebereglerstand 60 Verschiedene Fotos. Alle diese Fotos liegen in 60 getrennten globalen Variablen (z.B. BM1 bis BM60) und werden in verschiedenen Proceduren verwendet.

Ich lade also z.B. in der Proc >> Objekt_Laden << Das Bild in die Globale variable (Hier 1 von 60)

SUB_Bitmap1 := LoadGraphicsFile(SUB_STR_Pfad_PR_3 + 'PIC_01.JPG');

In einer anderen Procedur wird je nach Scrollbarstand das dementsprechende Bild weggeschrieben

if (SUB_ScrollBar.Position = 1) Then // Bild 1
BEGIN
SUB_Bitmap1 := LoadGraphicsFile(SUB_STR_Pfad_PR_ZOOM +'PIC_01.JPG'); SUB_Bitmap := SUB_Bitmap1;
END;

Dann hab ich zu aller verwirrung noch die Möglichkeit in einer anderen Procedur das Objekt in drei verschiedenen auflösungen zu laden.


Muß sagen fuktioniert alles wunderbar bis auf mein Speicherproblem. :wall:

Gibt`s noch Hoffnung auf eine "kleine Programmanpassung" ????
Ich denke eines meiner Hauptprobleme ist das ich mich dafür entschieden hatte die Bilder in globale Variablen zu schreiben. Da ich gelesen habe nach ende der Procedur wird Speicher wieder frei gemacht.

Gruß erstmal

fkerber 21. Jan 2009 21:07

Re: speicher wächst und wächst bei TBitmap Appl
 
Hallo!

Herzlich willkommen in der DP!

Was genau ist denn dein Speicherproblem?
Vllt. kannst du uns auch etwas mehr Code zeigen? (Ich sah jetzt bspw. die Verwendung der globalen Variablen)


Ciao, Frederic

Hoelderlein 22. Jan 2009 05:30

Re: speicher wächst und wächst bei TBitmap Appl
 
Hallo,

kann gerne noch etwas Code einfügen, ist aber denk ich sinnvoll wenn ich erst nochmal detailierter das Problem schildere.

- Ich hab also 60 Bilder auf festplatte (pro Objekt 60 * 4 Auflösungen * 10 Objekte = 2400 Bilder)
- Je nachdem welches Objekt mit welcher Auflösung geladen wird lade ich die dementsprechenden 60 Bilder in die 60 glob. Var.
- Danach kann das Objekt gedreht werden (mit Schieberegler in einer anderen Procedur)
- In der "Schiebereglerprocedur" wird einfach je nach Stand das dementsprechende Bild in das Timage geladen
- Das Ändern der Auflösung (gering - mittel - hoch) geschieht auch in einer eigenen Procedur
- Beim Zoomen wird die höchste Auflösung geladen (nur ein Bild auf dem der scrollbar gerade steht)

Das ist so vom Prinzip her die "Grundfunktion" des Programms und funktioniert alles wunderbar.

Jetzt das Problem :

Jedesmal wenn Bilder vom Datenträger in die 60 Globalen Variablen mit den Bildern geladen werden wird Arbeitsspeicher "verschwendet". Also der belegte Speicherplatz steigt mit jedem mal wo ich Objekte öffne betätige oder die Auflösung der Bilder ändere. Ich hab nicht einen Befehl drin der den Speicherplatz wieder freigibt.

Dies würde ich gerne machen bevor ich wieder Bilder vom Datenträger in die Variablen lade. Dies ist genau der Zeitpunkt bei der er die Variablen vom Speicherplatz her gesehen überschreiben bzw. erst freigeben und dann wieder belegen könnte. Dann währe das Speicherproblem beseitigt.

also kurz vor hier -->

SUB_Bitmap1 := LoadGraphicsFile(SUB_STR_Pfad_PR_3 + 'PIC_01.JPG');

Ich hab mit NIL bzw. FREE rumprobiert und keinen Erfolg gehabt.

Ich überleg mir mal wie ich ev. mehr Source hier reinkrieg und es aber noch übersichtlich bleibt. Ist viel Text im Programm ;o)

Gruß Frank :cheer:

Uwe Raabe 22. Jan 2009 07:25

Re: speicher wächst und wächst bei TBitmap Appl
 
Zitat:

Zitat von Hoelderlein
SUB_Bitmap1 := LoadGraphicsFile(SUB_STR_Pfad_PR_3 + 'PIC_01.JPG');

Nur so 'ne Vermutung: SUB_Bitmap1 ist ein TBitmap? Dann solltest du vor dieser Zuweisung ein SUB_Bitmap1.Free aufrufen (funktioniert übrigens auch, wenn SUB_Bitmap1 = nil ist). Andernfalls wird nämlich das Objekt in SUB_Bitmap1 nicht freigegeben und belegt bis zum Programmende Speicherplatz.

draeger1980 22. Jan 2009 07:30

Re: speicher wächst und wächst bei TBitmap Appl
 
Hallo,

mein Lösungsvorschlag wäre, die Dateipfade in eine TStringlist zu laden und über den ItemIndex kann mann ja in Verbindung mit der Scrollbar.position eine eindeutige Zuordnung schaffen.

So hat man immernur eine Variable für das TBitmap Objekt.

Luckie 22. Jan 2009 08:10

Re: speicher wächst und wächst bei TBitmap Appl
 
Also ohne Code wird das hier nichts. Code ist immer besser als tausend Worte.

Hoelderlein 22. Jan 2009 08:21

Re: speicher wächst und wächst bei TBitmap Appl
 
Danke erstmal für die Antworten.

Zitat:

SUB_Bitmap1 ist ein TBitmap? Dann solltest du vor dieser Zuweisung ein SUB_Bitmap1.Free aufrufen (funktioniert übrigens auch, wenn SUB_Bitmap1 = nil ist). Andernfalls wird nämlich das Objekt in SUB_Bitmap1 nicht freigegeben und belegt bis zum Programmende Speicherplatz.
SUB_Bitmap1 ist ein TBitmap. Ich hab schon probiert SUB_Bitmap1.Free bzw. SUB_Bitmap1.nil bzw. SUB_Bitmap1.avoid(nil) aufzurufen. Bekomme dann eine Fehlermeldung (wenns Prog läuft). Hab die jetzt nicht zur Hand da ich auf Arbeit bin. Werde wohl heute Abend nochmal Posten.

Zitat:

So hat man immernur eine Variable für das TBitmap Objekt.
In einem Pfad liegen 60 Bilder. Diese werden in 60 Variablen geschrieben. Letztendlich hab ich dann nur eine Variable (Bild) die auf dem Schirm angezeigt wird. Der Scrollbar kann im Moment "sehr fleissend" Bewegt werden und die Bilder werden sauber nachgeführt. Würde ich es so machen (wie ich dich verstanden habe) müsste bei jeder Scrollbarpositionsänderung wieder ein Bild geladen werden. Vorteil ich hätte nur eine Belegte Variable. Nachteil läuft nicht rund und sieht dann für den Anwender nicht sauber aus.
Ursprünglich hatte ich mal diese Variante, hab dann aber auf die jetzige umgetippt.

Wenns Sauber fluffig laufen soll brauch ich doch die 60 Bildern in irgend einer Form als Variable oder ??

Gruß

Frank

Hoelderlein 22. Jan 2009 08:23

Re: speicher wächst und wächst bei TBitmap Appl
 
Zitat:

Also ohne Code wird das hier nichts. Code ist immer besser als tausend Worte.
OK, hast recht. Heute Abend gibt`s Code.

Frank

Uwe Raabe 22. Jan 2009 08:40

Re: speicher wächst und wächst bei TBitmap Appl
 
SUB_Bitmap1.Free gibt hier keine Fehlermeldung, kann aber auch durch ein
Delphi-Quellcode:
if SUB_Bitmap1 <> nil then SUB_Bitmap1.Free;
ersetzt werden.

SUB_Bitmap1.nil ist genauso ungültig wie SUB_Bitmap1.avoid(nil) und sollte schon beim Compilieren angemeckert werden.

Uwe

nuclearping 22. Jan 2009 08:57

Re: speicher wächst und wächst bei TBitmap Appl
 
Nach meiner Erfahrung leaken Funktionen, die eine TBitmap zurückliefern.

Leak:
Delphi-Quellcode:
function DoSomething: TBitmap;
begin
  Result := TBitmap.Create;
  ...
end;
Kein Leak:
Delphi-Quellcode:
procedure DoSomething (var Bitmap: TBitmap);
begin
  Bitmap := TBitmap.Create;
  ...
end;

Muetze1 22. Jan 2009 09:07

Re: speicher wächst und wächst bei TBitmap Appl
 
@Nuclearping: Die beiden Funktionen machen keinen Unterschied und leaken beide nicht, wenn ausserhalb das intern erzeugt Bitmap freigegeben wird. Und genau da liegt das eigentliche Problem: Der Code ist unübersichtlich!

Du weisst als Aufrufer niemals, ob du die Bitmap freigeben darfst. Beim ersten könnte die Instanz aus einem Pool stammen und wem anders gehören und beim zweiten Aufruf weiss man nicht, ob man vorher eine erzeugen muss oder nicht. Von daher sollte man sich an die Faustformel halten: Anlegen und Freigeben möglichst auf der gleichen Ebene.

In diesem Falle würde es bedeutet, dass man das Bitmap ausserhalb erzeugt und ausserhalb auch wieder freigibt. In der Funktion selbst kann dann mit dem Bitmap gearbeitet werden, aber die Instanz bleibt dabei unverändert. Nebenbei wird dadurch die Nutzung der try/finally Blöcke erleichtert und erlauben somit in Verbindung mit Bitmaps solche "Resourcenschutzblöcke".

Delphi-Quellcode:
Procedure Aufrufer;
var
  lBitmap: TBitmap;
begin
  lBitmap := TBitmap.Create;
  try
    MachWas(lBitmap);
  finally
    lBitmap.Free;
  end;
end;

procedure MachWas(const ABitmap: TBitmap);
begin
  ABitmap.Canvas.FillRect(Bounds(10, 10, 10, 10));
end;

nuclearping 22. Jan 2009 09:43

Re: speicher wächst und wächst bei TBitmap Appl
 
Zitat:

Zitat von Muetze1
@Nuclearping: Die beiden Funktionen machen keinen Unterschied und leaken beide nicht, wenn ausserhalb das intern erzeugt Bitmap freigegeben wird.

Hast du's probiert oder ist es eine Vermutung? ;) Wie schon gesagt: Erstere leaked nach meiner Erfahrung. Es entstehen keine offensichtlichen Speicherlecks, die durch FastMM oder ähnliches erfasst werden. Im Task-Manager sieht man aber die Akkumulierung.

Wir hatten in unserer Anwendung dieses Problem mit Routinen, die mehrere Tage / Wochen blasenfrei durchlaufen müssen. Wir haben da richtig lange gesucht, um jeden Leak zu finden und zu eliminieren. Und das war einer davon. Scheinbar leaked da der Overhead.

Muetze1 22. Jan 2009 14:05

Re: speicher wächst und wächst bei TBitmap Appl
 
Zitat:

Zitat von nuclearping
Zitat:

Zitat von Muetze1
@Nuclearping: Die beiden Funktionen machen keinen Unterschied und leaken beide nicht, wenn ausserhalb das intern erzeugt Bitmap freigegeben wird.

Hast du's probiert oder ist es eine Vermutung? ;)

Probiert und Wissen, da ich gleiches wie du beschrieben hast selbst bei einer Anwendung mit einer großen Bitmapnutzung durch habe und es gibt definitiv keinen Unterschied dabei. Compiler hierbei D7 & RAD2007. Bei beiden kein Unterschied und kein Leak.

Hoelderlein 22. Jan 2009 19:54

Re: speicher wächst und wächst bei TBitmap Appl
 
Hallo an alle,

:dancer: ich habs wiedererwartend selbst hinbekommen. :dancer2:

Hab muß ich zugeben ein Tip von einem Kollegen bekommen.

Wie zuvor beschrieben habe ich schon mit Free rumprobiert. Allerdings ohne Erfolg.

Fehler war das ich zu dem Zeitpunkt des Free befehl noch nicht den Create gemacht hatte. Also direkt nach dem Programmstart.
Ich war fälschlicher weiße davon ausgegangen das ich Free sogar ohne create machen kann. Scheint mir nun nicht mehr so. ;o)

Zudem hatte ich Bitmap.create probiert. war wohl nicht ok so.

Mit SUB_Bitmap1 := TBitmap.Create; funktioniert`s super

Bin halt wohl doch kein richtiger Programmierer. Eher so wie die Fußballer die nicht wirklich spielen können und durch rennen und Grätschen den Stammplatz in der Bezirksklasse halten können.

Gruß an alle :zwinker:

nuclearping 23. Jan 2009 10:02

Re: speicher wächst und wächst bei TBitmap Appl
 
Zitat:

Zitat von Muetze1
Probiert und Wissen, da ich gleiches wie du beschrieben hast selbst bei einer Anwendung mit einer großen Bitmapnutzung durch habe und es gibt definitiv keinen Unterschied dabei. Compiler hierbei D7 & RAD2007. Bei beiden kein Unterschied und kein Leak.

Na dann hatten wir hier vlt. nur Halluzinationen. http://ugly.plzdiekthxbye.net/small/s000.gif


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