Dobry wieczór!Mycie w programie MakeScreenshot?
W bieżącym projekcie mam raczej niepokojący wyciek pamięci, którego nie mogę podłączyć.
Opuściłem aplikację uruchomioną na noc ze standardowym używaniem, a kiedy obudziłem się 8 godzin później, zużywało ~ 750 MB pamięci, podczas gdy zaczynało się ~ 50 MB. Menedżer zadań systemu Windows nie nadaje się do sprawdzania przecieków, poza tym, że pozwala stwierdzić, że taki istnieje w pierwszej kolejności.
Rozwiązałem już kilka innych wycieków pamięci, z których główny jest związany z TGlowEffect
Firemonkeys. Nie jest wykrywany przez ReportLeaksOnShutdown
, ale użycie pamięci staje się nadmiernie nadmierne w przypadku dynamicznie modyfikowanego obiektu (np. Zmiany obrotu lub skali).
Śledziłem go do licznika czasu (i wyłączając go całkowicie zatrzymuje wyciek), i jeśli to możliwe, potrzebuję pomocy w jego naprawieniu.
Opis: Ten kod wykorzystuje funkcję Firemonkey MakeScreenshot
zapisać wizualny wygląd TPanel (SigPanel)
do TMemoryStream
. Te dane strumieniowe są następnie przesyłane do zdalnego serwera FTP przy użyciu standardowego kodu (patrz poniżej). Wewnątrz SigPanel
istnieją dzieci: 4 TLabel
, 1 TRectangle
i 6 TImage
.
Uwagi: CfId
jest globalny łańcuch i jest generowany w oparciu na losowej extended
wartości pływaka, który jest następnie zaszyfrowaną wraz z DateTime w formacie yyyymmdd_hhnnsszzz
. Generowanie to jest wykonywane po utworzeniu formularza i powtarza się, dopóki nie uzyska poprawnego CfId
(tj. Nie zawiera znaków niedozwolonych w nazwach plików systemu Windows). Po uzyskaniu poprawnego CfId
, nie uruchamia się wcale (ponieważ nie ma już potrzeby generowania nowego identyfikatora). To pozwala mi prawie całkowicie wyeliminować szansę duplikowania CfId
.
Kod w stoperze wygląda następująco;
var
i : Integer;
SigStream : TMemoryStream;
begin
SigStream := TMemoryStream.Create;
SigPanel.MakeScreenshot.SaveToStream(SigStream);
SigPanel.MakeScreenshot.Free;
if VT2SigUp.Connected then
begin
VT2SigUp.Put(SigStream,'Sig_'+CfId+'.png',False);
end else
begin
VT2SigUp.Connect;
VT2SigUp.Put(SigStream,'Sig_'+CfId+'.png',False);
end;
SigStream.Free;
end;
z samowyzwalaczem NIE uruchomiony, funkcje kodu całkowicie bez przecieków i ReportMemoryLeaksOnShutdown
robi NIE wygenerować wiadomość. Po włączeniu timera i zezwoleniu na "uruchomienie" co najmniej raz, dostaję dużo wycieku, który rośnie, tym więcej razy działa timer. Zgłaszane przecieki są następujące;
Small Block Leaks
1 - 12 Bytes: Unknown x 1
13 - 20 Bytes: TList x 5, Unknown x 1
21 - 28 Bytes: TFont x 2, TGradientPoint x 8, TGradientPoints x 4, Unknown x 4
29 - 36 Bytes: TObjectList<FMX.Types.TCanvasSaveState> x 1, TBrushBitmap x 4,
TBrushGrab x 4, TPosition x 24, TGradient x 4, UnicodeString x1
37 - 44 Bytes: TBrushResource x 4
53 - 60 Bytes: TBrush x 4
61 - 68 Bytes: TBitmap x 5
69 - 76 Bytes: TD2DCanvasSaveState x 1
205 - 220 Bytes: TCanvasD2D x 1
Sizes of Medium and Large Block Leaks
200236
jako przebiegów czasowych, wartości te są mnożone n razy ( n oznacza liczbę razy czasomierz run). Średnie i duże bloki mają wartość z roku 20023636 (np. Jeśli zegar pracował 3 razy, to jest to 200236, 200236, 200326).
Zainteresowanie, jeśli usunę kod związany z MakeScreenshot
, wyciek już nie istnieje, a zużycie pamięci pozostaje na nieco normalnym poziomie. Oprócz zwykłego użycia pamięci, nie ma nic niezwykłego i nie ma żadnych wycieków. Próbowałem już wielu próbek kodu, zarówno z zapisaniem do strumienia i przesłaniem z niego, jak i zapisaniem do strumienia> Plikem, a następnie przesłaniem pliku, ale wydaje się, że wyciek w samej funkcji.Dodałem nawet MakeScreenshot.Free
kiedy odkryłem przeciek tutaj, ale po prostu nie mogę go podłączyć, i oczywiście użyłem try..finally
w jednym z moich "testów" kodu.
Uruchomiłem nawet kod z GDI + jako typ kanwy i wystąpił tam taki sam wyciek (jedyną zmianą jest to, że D2D przesyła referencje GDI +).
Byłbym bardzo wdzięczny za wszelkie badania lub notatki, które ktoś ma na ten temat, a ponadto rozwiązanie tego problemu.
wierzę, po prostu znaleźć przeciek pamięci w FM (: – ComputerSaysNo
wierzę ustawienie 'ReportMemoryLeaksOnShutdown: = True;' w inicjalizacji twojej aplikacji powinno wystarczyć, aby pokazać, co jest nieszczelne ... –
@DorinDuminica Wierzę, że tak, ale uważam, że znalazłem problem polegający na tym, że 'Wynik' w' FMX.Types.MakeScreenshot' nie jest w rzeczywistości są zwalniane, po prostu wywołują "Result.Canvas.EndScene" i nigdy go nie uwalniają! @Je rryDodge Tak właśnie uciekłem, aby dowiedzieć się, co było nieszczelne, dokładnie tak, jakbym nie był w stanie uzyskać dokładnej listy bez niego :) –