Delphi-Forum.de Delphi-Library.de
C-Sharp-Forum.de C-Sharp-Library.de
Registrieren Login Suche Hilfe Sitemap
Riesiges Speicherleck bei Verwendung von GDI
spacer
Autor Nachricht
Sascha L
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star

Beiträge: 25
Dabei seit: 25.07.2004



BeitragVerfasst: Di 23.02.10 21:03  Antworten mit Zitat Beitrag melden
Hallo,

ich habe ein riesiges Speicherleck, welches ich einfach nicht finde. Ich hoffe, dass mir hier jemand weiterhelfen kann. Wenn ich folgenden Code z.B. 1000mal ausführe, habe ich ein Speicherleck von 300 KB!


ausblenden C#-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
Graphics gbuffer = CreateGraphics();
IntPtr screenDC = gbuffer.GetHdc();
IntPtr memDC = CreateCompatibleDC(screenDC);
IntPtr bufferDC = CreateCompatibleBitmap(screenDC, Width, Height);

Graphics g = Graphics.FromHdc(memDC);
g.Clip = new Region(new Rectangle(0, 0, Width, Height));

IntPtr old = SelectObject(memDC, bufferDC);

g.Clear(Color.FromArgb((int)color));
g.Dispose();

BitBlt(screenDC, 0, 0, Width, Height, memDC, 0, 0, 0x00CC0020);

SelectObject(memDC, old);

DeleteObject(bufferDC);
DeleteDC(memDC);
gbuffer.ReleaseHdc(screenDC);
gbuffer.Dispose();


Gruß
Sascha
Private Nachricht sendenPosting in privater Nachricht zitieren
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic star
Chefentwickler

Beiträge: 17441
Erhaltene Danke: 95
Dabei seit: 07.07.2002
Wohnort: Server-Souterrain

Win 7
Delphi Prism, C# (VS 2010)
BeitragVerfasst: Di 23.02.10 22:33  Antworten mit Zitat Beitrag melden
Bist Du sicher, dass es ein Speicherleck ist oder kann es sein, dass der GC einfach noch nicht aufgeräumt hat?

_________________
I am of peace. Always.
Private Nachricht sendenPosting in privater Nachricht zitieren Webseite dieses Mitglieds besuchen
Sascha L
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star

(Threadstarter)

Beiträge: 25
Dabei seit: 25.07.2004



BeitragVerfasst: Di 23.02.10 22:51  Antworten mit Zitat Beitrag melden
Hi,

ja, da bin ich mir aus folgenden zwei Gründen sicher:

a) Es sind fast nur native Funktionen, auf die der GC keinen Einfluss hat. Und selbst wenn ich GC.Collect() und WaitForPendingFinalizers() aufrufe, ändert sich am Speicherleck nichts

b) Wenn ich den Code mehr als 1000mal aufrufe, z.B. 100.000mal ist GDI systemweit im Eimer. D.h. selbst wenn ich meine Anwendung beende, können andere Anwendungen nicht mehr korrekt zeichnen, weil wohl ja nur eine bestimmte Anzahl an GDI Objekten systemweit möglich sind und die anscheinend von mir nicht richtig frei gegeben werden.


EDIT: Hab total vergessen zu erwähnen, dass ich das Problem auf Windows Mobile mit dem .NET CF habe! Ob es auf dem PC auch der Fall ist, weiß ich nicht.
Private Nachricht sendenPosting in privater Nachricht zitieren
Sascha L
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star

(Threadstarter)

Beiträge: 25
Dabei seit: 25.07.2004



BeitragVerfasst: Mi 24.02.10 16:49  Antworten mit Zitat Beitrag melden
Hab das Problem.

"g" ist das Problem. Trotz g.Dispose() und g = null bleibt es im Speicher. Erst ein Collect() und WaitForPendingFinalizers() löscht es. Die GC-Funktionen kann ich aber nicht bei jedem Zeichnen aufrufen, da das Zeichnen sonst extrem lahm wird. Gibt es sonst noch eine Möglichkeit "g" komplett zu löschen?
Private Nachricht sendenPosting in privater Nachricht zitieren
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic star
Moderator

Beiträge: 2864
Erhaltene Danke: 11
Dabei seit: 12.11.2005
Wohnort: Brackenheim

Win 7
F#, C# (VS2010)
BeitragVerfasst: Mi 24.02.10 21:02  Antworten mit Zitat Beitrag melden
Ich kann es zwar nicht testen, und du hast ja eigentlich recht eindeutige Ergebnisse, trotzdem muss ich einwerfen: Das kann einfach nicht sein ;) .
Graphics.Dispose gibt das Handle frei und unterdrückt den Finalizer, GDI und GC können also eigentlich nicht zusammenhängen. Und die ~16 Bytes pro Graphics-Instanz dürften es auch nicht raushauen :) .

_________________
>λ=
Private Nachricht sendenPosting in privater Nachricht zitieren Webseite dieses Mitglieds besuchen
Sascha L
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star

(Threadstarter)

Beiträge: 25
Dabei seit: 25.07.2004



BeitragVerfasst: Do 25.02.10 00:10  Antworten mit Zitat Beitrag melden
Also ich kann nur so viel sagen, dass es bei mir eindeutig das Graphics-Objekt ist. Ich habe es noch so weit optimiert, dass ich gbuffer nicht mehr benötigte (nutze nun GetDC), aber g brauch ich (der obige Code ist nämlich nur ein Beispiel). Wenn ich g nicht verwende, gibt es kein Speicherleck. Nutze ich g, gibt es ein Speicherleck. Rufe ich den GC nach g.Dispose() und g = null auf, ist das Speicherleck ebenfalls weg. Das Problem ist nur, dass in diesem Falle die Performance natürlich stark leidet, wenn ich jedes Mal den GC aufrufen muss.

Rufe ich den GC nicht auf, wird der Speicher zu keiner Zeit wieder freigegeben. Was wie gesagt bei Windows Mobile fatal ist, weil mal schnell 10-20 MB zusammen kommen und das ist für die meisten WM-Geräte schon zu viel, sodass entweder nichts mehr reagiert oder andere Anwendungen nichts mehr zeichnen können, da alle GDI-Objekte vergeben sind (gibt nur eine maximale Anzahl erlaubter GDI-Objekte).
Private Nachricht sendenPosting in privater Nachricht zitieren
Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.


Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.
Beiträge vom vorherigen Thema anzeigen:   
home home