![]() |
FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Hallo zusammen,
Auf meine alten Tage muss ich in einem mit XE2 erstellten Projekt ein Memoryleak suchen. Ich habe FastMM mit Fulldebugmode eingebunden und schon mal einige Leaks gefixt. Allerdings waren dies beim beenden des Dienstes nicht freigegebene Objekte. Das Problem tritt aber zur Laufzeit auf. Nun: Trotz Suche in diversern Foren haben ich nicht genau herausgefunden wie ich den Stacktrace deuten kann. Zum Beispiel hier:
Code:
Es scheint sich um eine generische Liste zu handeln. Aber wo ist springende Punkt um welche Liste/Funktion es sich handelt?
A memory block has been leaked. The size is: 12
This block was allocated by thread 0x24A4, and the stack trace (return addresses) at the time was: 404ADE [System.pas][System][@GetMem$qqri][3454] 468660 [System.Generics.Defaults.pas][System.Generics.Defaults][Generics.Defaults.MakeInstance$qqrpvi][145] 468CF3 [System.Generics.Defaults.pas][System.Generics.Defaults][Generics.Defaults.Comparer_Selector_Binary$qqrp24System.Typinfo.TTypeInfoi][760] 4695A4 [System.Generics.Defaults.pas][System.Generics.Defaults][Generics.Defaults._LookupVtableInfo$qqr49System.Generics.Defaults.TDefaultGenericInterfacep24System.Typinfo.TTypeInfoi][1441] 67893A [System.Generics.Defaults.pas][uDetectionObjects][Generics.Defaults.%TComparer__1$20System.Types.TPointF%.Default$qqrv][1642] 673AE8 [System.Generics.Collections.pas][uDetectionObjects][Generics.Collections.%TList__1$20System.Types.TPointF%.$bctr$qqrv][663] 815B8B [uDataStorage.pas][uDataStorage][TDataStorage.GetPolygonFromXml$qqrx20System.UnicodeString][363] 81B21D [uDataStorage.pas][uDataStorage][TDataStorage.AddParkingLots$qqrip25Udetectionobjects.TCameraii][1169] 70A4F5 [MemDS][TMemDataSet.GetFieldData$qqrp14Data.Db.TFieldpvo] 6DF4D4 [Data.DB.pas][Data.DB][Db.TDataSet.FieldByName$qqrx20System.UnicodeString][11805] 8147E2 [uDataStorage.pas][uDataStorage][TDataStorage.GetConfiguration$qqrv][171] The block is currently used for an object of class: Unknown The allocation number is: 5291 Current memory dump of 256 bytes starting at pointer address 7EF6CFE8: 5C A6 87 00 01 00 00 00 08 00 00 00 86 14 66 78 00 00 00 00 61 D2 F6 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 82 17 00 00 DE 4A 40 00 6B 5F 40 00 DA 65 40 00 A0 5F 40 00 DA 65 40 00 BF 40 45 00 67 43 45 00 6A 06 6B 00 63 3A 6B 00 8B 91 66 00 2D 43 6B 00 A4 24 00 00 3C 26 00 00 FA 4A 40 00 89 5F 40 00 25 66 40 00 C2 5F 40 00 CF 5F 40 00 51 41 45 00 CF 5F 40 00 A6 43 45 00 CF 5F 40 00 C3 07 6B 00 CF 5F 40 00 08 00 00 00 88 15 40 00 9A 33 A4 85 98 D2 8A 00 80 80 80 80 65 CC 5B 7A 80 80 80 80 00 00 00 00 B1 C7 F6 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 18 00 00 DE 4A 40 00 6B 5F 40 00 DA 65 40 00 4E EE 83 00 91 ED 83 00 5E D4 83 00 36 93 26 00 58 FB 45 00 D9 FE 45 00 BE 7B 40 00 8A 33 A9 76 D8 15 00 00 3C 26 00 00 FA 4A 40 00 89 5F 40 00 \ ¦ ‡ . . . . . . . . . † . f x . . . . a Ò ö ~ . . . . . . . . . . . . . . . . ‚ . . . Þ J @ . k _ @ . Ú e @ . * _ @ . Ú e @ . ¿ @ E . g C E . j . k . c : k . ‹ ‘ f . - C k . ¤ $ . . < & . . ú J @ . ‰ _ @ . % f @ . Â _ @ . Ï _ @ . Q A E . Ï _ @ . ¦ C E . Ï _ @ . Ã . k . Ï _ @ . . . . . ˆ . @ . š 3 ¤ … ˜ Ò Š . € € € € e Ì [ z € € € € . . . . ± Ç ö ~ . . . . . . . . . . . . . . . . † . . . Þ J @ . k _ @ . Ú e @ . N î ƒ . ‘ í ƒ . ^ Ô ƒ . 6 “ & . X û E . Ù þ E . ¾ { @ . Š 3 © v Ø . . . < & . . ú J @ . ‰ _ @ . Oder hier:
Code:
Es sind hier uDetection.pas und uDataStorage.pas aufgeführt.
A memory block has been leaked. The size is: 12
This block was allocated by thread 0x24A4, and the stack trace (return addresses) at the time was: 404ADE [System.pas][System][@GetMem$qqri][3454] 468660 [System.Generics.Defaults.pas][System.Generics.Defaults][Generics.Defaults.MakeInstance$qqrpvi][145] 468CF3 [System.Generics.Defaults.pas][System.Generics.Defaults][Generics.Defaults.Comparer_Selector_Binary$qqrp24System.Typinfo.TTypeInfoi][760] 4695A4 [System.Generics.Defaults.pas][System.Generics.Defaults][Generics.Defaults._LookupVtableInfo$qqr49System.Generics.Defaults.TDefaultGenericInterfacep24System.Typinfo.TTypeInfoi][1441] 67893A [System.Generics.Defaults.pas][uDetectionObjects][Generics.Defaults.%TComparer__1$20System.Types.TPointF%.Default$qqrv][1642] 673AE8 [System.Generics.Collections.pas][uDetectionObjects][Generics.Collections.%TList__1$20System.Types.TPointF%.$bctr$qqrv][663] 6733A7 [uDetectionObjects.pas][uDetectionObjects][TObjectPolygon.$bctr$qqrii][1137] 671F2B [uDetectionObjects.pas][uDetectionObjects][TObjectSensor.$bctr$qqrii][587] 6729DC [uDetectionObjects.pas][uDetectionObjects][TParkingLot.SetObjectSensorActive$qqrxo][865] 81B1C4 [uDataStorage.pas][uDataStorage][TDataStorage.AddParkingLots$qqrip25Udetectionobjects.TCameraii][1164] 70A4F5 [MemDS][TMemDataSet.GetFieldData$qqrp14Data.Db.TFieldpvo] The block is currently used for an object of class: Unknown The allocation number is: 5279 Current memory dump of 256 bytes starting at pointer address 7EF6CF50: 5C A6 87 00 01 00 00 00 08 00 00 00 F7 77 42 79 00 00 00 00 20 7F F6 7E 00 00 00 00 00 00 00 00 68 36 41 00 00 00 00 00 AB 14 00 00 DE 4A 40 00 60 86 46 00 F3 8C 46 00 A4 95 46 00 3A 89 67 00 E8 3A 67 00 8B 5B 81 00 1D B2 81 00 F5 A4 70 00 D4 F4 6D 00 E2 47 81 00 A4 24 00 00 A4 24 00 00 FA 4A 40 00 C6 A4 40 00 C9 A1 40 00 00 A2 40 00 72 A3 40 00 FF BE 7C 00 38 29 77 00 9A 80 7C 00 E8 92 7C 00 36 79 6F 00 76 94 7C 00 0C 00 00 00 00 00 00 00 79 EB 99 87 5C A6 87 00 01 00 00 00 08 00 00 00 86 14 66 78 00 00 00 00 61 D2 F6 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 82 17 00 00 DE 4A 40 00 6B 5F 40 00 DA 65 40 00 A0 5F 40 00 DA 65 40 00 BF 40 45 00 67 43 45 00 6A 06 6B 00 63 3A 6B 00 8B 91 66 00 2D 43 6B 00 A4 24 00 00 3C 26 00 00 FA 4A 40 00 89 5F 40 00 \ ¦ ‡ . . . . . . . . . ÷ w B y . . . . ö ~ . . . . . . . . h 6 A . . . . . « . . . Þ J @ . ` † F . ó Œ F . ¤ • F . : ‰ g . è : g . ‹ [ . . ² . õ ¤ p . Ô ô m . â G . ¤ $ . . ¤ $ . . ú J @ . Æ ¤ @ . É ¡ @ . . ¢ @ . r £ @ . ÿ ¾ | . 8 ) w . š € | . è ’ | . 6 y o . v ” | . . . . . . . . . y ë ™ ‡ \ ¦ ‡ . . . . . . . . . † . f x . . . . a Ò ö ~ . . . . . . . . . . . . . . . . ‚ . . . Þ J @ . k _ @ . Ú e @ . * _ @ . Ú e @ . ¿ @ E . g C E . j . k . c : k . ‹ ‘ f . - C k . ¤ $ . . < & . . ú J @ . ‰ _ @ .
Code:
Hier wird sogar das Objekt: TObjectSensor aufgeführt und drei units welche von uns sind.
A memory block has been leaked. The size is: 52
This block was allocated by thread 0x24A4, and the stack trace (return addresses) at the time was: 404ADE [System.pas][System][@GetMem$qqri][3454] 405F6B [System.pas][System][TObject.NewInstance$qqrv][13000] 4065DA [System.pas][System][@ClassCreate$qqrpvzc][14164] 671EE6 [uDetectionObjects.pas][uDetectionObjects][TObjectSensor.$bctr$qqrii][584] 4138C9 [FastMM4.pas][FastMM4][DebugFreeMem$qqrpv][8900] 6729DC [uDetectionObjects.pas][uDetectionObjects][TParkingLot.SetObjectSensorActive$qqrxo][865] 81B1C4 [uDataStorage.pas][uDataStorage][TDataStorage.AddParkingLots$qqrip25Udetectionobjects.TCameraii][1164] 70A4F5 [MemDS][TMemDataSet.GetFieldData$qqrp14Data.Db.TFieldpvo] 6DF4D4 [Data.DB.pas][Data.DB][Db.TDataSet.FieldByName$qqrx20System.UnicodeString][11805] 8147E2 [uDataStorage.pas][uDataStorage][TDataStorage.GetConfiguration$qqrv][171] 8386C0 [uDetectionCore.pas][uDetectionCore][TDetectionCore.OnDatabaseConnected$qqrp14System.TObject][186] The block is currently used for an object of class: TObjectSensor The allocation number is: 5273 Current memory dump of 256 bytes starting at pointer address 7EDE0470: A0 A4 66 00 D0 60 DF 7E E0 62 DF 7E 19 00 00 00 0A 00 00 00 60 00 00 00 64 00 00 00 5C 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 B0 CF DF 7E 00 00 00 00 8F 68 D5 C4 00 00 00 00 71 0B DE 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BE 14 00 00 DE 4A 40 00 6B 5F 40 00 E9 BB 40 00 DA 65 40 00 DE B9 7F 00 3A B4 7F 00 9B C9 7F 00 92 7A 80 00 70 7B 80 00 26 C0 80 00 EC 5B 81 00 A4 24 00 00 A4 24 00 00 FA 4A 40 00 89 5F 40 00 25 66 40 00 C2 5F 40 00 4F BC 40 00 5B BB 40 00 F9 98 40 00 E9 97 40 00 3F 60 40 00 82 5F 40 00 25 66 40 00 30 00 00 00 10 A8 7F 00 A5 5F A7 86 98 D2 8A 00 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 5A A0 58 79 80 80 80 80 00 00 00 00 B1 04 DE 7E * ¤ f . Ð ` ß ~ à b ß ~ . . . . . . . . ` . . . d . . . \ . . . . . . . . . . . . . . . ° Ï ß ~ . . . . h Õ Ä . . . . q . Þ ~ . . . . . . . . . . . . . . . . ¾ . . . Þ J @ . k _ @ . é » @ . Ú e @ . Þ ¹ . : ´ . › É . ’ z € . p { € . & À € . ì [ . ¤ $ . . ¤ $ . . ú J @ . ‰ _ @ . % f @ . Â _ @ . O ¼ @ . [ » @ . ù ˜ @ . é — @ . ? ` @ . ‚ _ @ . % f @ . 0 . . . . ¨ . ¥ _ § † ˜ Ò Š . € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € Z * X y € € € € . . . . ± . Þ ~ Macht die Reihenfolge der Auflistung einen Sinn? Wenn ja welchen? Villeicht gibt es ja irgendwo eine Erklärung dazu - nur finde ich sie nicht? Danke für Eure Anregungen. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Folgendes Projekt
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE} {$R *.res} uses FastMM4, Unit2 in 'Unit2.pas'; begin ReportMemoryLeaksOnShutdown := True; createLeak(); end.
Delphi-Quellcode:
erzeugt folgende Ausgabe:
unit Unit2;
interface procedure createLeak(); forward; implementation procedure createLeak(); begin TObject.Create(); end; end.
Code:
--------------------------------2014/9/8 13:33:46--------------------------------
A memory block has been leaked. The size is: 12 This block was allocated by thread 0x1700, and the stack trace (return addresses) at the time was: 4040D6 [System.pas][System][@GetMem$qqri][4305] 4048CB [System.pas][System][TObject.NewInstance$qqrv][15436] 404ECE [System.pas][System][@ClassCreate$qqrpvzc][16746] 404900 [System.pas][System][TObject.$bctr$qqrv][15500] 405B50 [System.pas][System][@StartExe$qqrp23System.PackageInfoTablep17System.TLibModule][21884] 41D35B [Unit2.pas][Unit2][createLeak$qqrv][10] 41F3FD 76B3338A [BaseThreadInitThunk] 777F9F72 [Unknown function at RtlInitializeExceptionChain] 777F9F45 [Unknown function at RtlInitializeExceptionChain] The block is currently used for an object of class: TObject The allocation number is: 110 Current memory dump of 256 bytes starting at pointer address 7EF6F520: 10 14 40 00 00 00 00 00 31 85 50 19 78 85 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . @ . . . . . 1 … P . x … B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . --------------------------------2014/9/8 13:33:46-------------------------------- This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer): 5 - 12 bytes: TObject x 1 Note: Memory leak detail is logged to a text file in the same folder as this application. To disable this memory leak check, undefine "EnableMemoryLeakReporting". Gehe von unten die letzten dir bekannten Units durch. In diesem Fall ist es
Das wird nie freigegeben. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
O.K von unten ist ja schon mal ein sehr guter Hinweis. Ist es möglich die Anzahl der Leaks irgendwie herauszufinden? Eigentlich ist es mir (erstmal) egal wenn beim beenden des Programms ein Objekt welches beim Start erzeugt wurde nicht freigegeben wird. Schön wäre es aber nach einer gewissen Laufzeit zu sehen ob das 12Byte Leak XY 100 Mal aufgetreten ist - oder eben nur ein Mal. Ist so was möglich?
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Wenn du in deiner DPR ...
Delphi-Quellcode:
... schreibst, solltest beim Beenden des Programms eine entsprechende Meldung erhalten.
program ...;
uses ...; begin ReportMemoryLeaksOnShutdown := TRUE; ... end. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Hallo Nuclearping,
die Meldungen erhalte ich ja (siehe Post 1). Meine Frage bezog sich auf das deuten der Meldungen. Insbesondere wenn es sich um eine "unknown class" handelt und mehrere units/funktionen aufgeführt sind. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Hallo!
Was passiert denn in den 2 Codestellen: 8147E2 [uDataStorage.pas][uDataStorage][TDataStorage.GetConfiguration$qqrv][171] 8386C0 [uDetectionCore.pas][uDetectionCore][TDetectionCore.OnDatabaseConnected$qqrp14System.TO bject][186] Christoph |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
Objekte, die leaken, erscheinen dann mit einer stetig wachsenden Anzahl in der Liste. How do I find memory leaks at run time with FastMM4? ![]() Strategy or tools to find “non-leak” memory usage problems in Delphi? ![]() Step by step Anleitung:
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
![]() Die UI bietet ein Tab "Statistics" an, welches Dir genau anzeigt, wie viele Objekte einer Klasse (mit Records funktioniert es mit EInschränkungen ebenso) erzeugt wurden, wie viele maximal gleichzeitig lebten etc. Grüße, S. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Hallo Sahimba,
Ich hab mir Dein Tool schon angesehen. Mein momentan knausriger Arbeitgeber (was Delphi anbelangt) hat aber abgewunken. Obwohl der Preis ja nicht überaus hoch ist. Ich versuchs mal mit dem Tip von mjustin. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Hallo.
Zitat:
Darf ich fragen, ob es Probleme bei der Installation der Verwendung gab oder wie der erste Eindruck war? Ich glaube, am Userinterface sollte ic schon noch bissl schrauben. Grüße, S. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
Zitat:
![]() |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Das "Übliche", also Objekte, Pointer und sogar unfinalisierte dynamische Arrays zeigt dir der ShutDown-Report aber in der Regel schon an, bzw. gibt in Form von "Unknown" Hinweise darauf.
Aber du hast prinzipiell schon recht. Mir ging es hier auch nur darum, ihm eine "einfache" Möglichkeit anzubieten, an Informationen zu kommen, die ihm vlt. helfen. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:
Code:
Nach vier Tagen sieht der Report so aus:
FastMM State Capture:
--------------------- 62075K Allocated 11139K Overhead 85% Efficiency Usage Detail: 69841512 bytes: Unknown x 2736 213740 bytes: UnicodeString x 1967 24908 bytes: TOnDemandConverter x 479 19188 bytes: TCriticalSection x 533 15200 bytes: TByteMap x 152
Code:
Und wenn ich den Service beende - keine Meldung von FastMM! Also eigentlich alles super oder?
FastMM State Capture:
--------------------- 62111K Allocated 16222K Overhead 79% Efficiency Usage Detail: 69848804 bytes: Unknown x 2773 231868 bytes: UnicodeString x 2091 24908 bytes: TOnDemandConverter x 479 19188 bytes: TCriticalSection x 533 15200 bytes: TByteMap x 152 Aber im Anhang sind zwei Screenshots zum identischen Zeitpunkt wie oben. Also beim Start und vor dem beenden. Dort sieht man dass beim Start ca. 90MB private Bytes und nach vier Tagen 600MB beansprucht werden. Nach zwei Wochen sinds dann 2GB und irgendwann crasht der Service. Was hab ich (oder FastMM) übersehen? |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Ich habe keine Ahnung, aber könnten es vielleicht Dinge sein die von DLLs alloziiert werden?
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Dann könnten es höchstens Windows DLL's sein. Andererseits - wohl kaum? Hmhh.. Ich bin ratlos.
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Nur mal so überlegt:
Delphi-Quellcode:
Meiner Meinung nach frisst der kleiner Speicherfresser während der Laufzeit des Programms immer mehr Speicher auf, da immer eine neue Instanz kreiert wird. Allerdings wird beim Beenden des Programms alles freigegeben, da der Owner = self ist.
procedure TForm1.Timer1OnTimer(Sender: TObject);
var SpeicherFresser : TEdit; begin Speicherfresser := TEdit.Create(self); end; |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
Bei ![]() Wenn du mit Inline Hooks vertraut bist, könntest du einfach mal die genannten APIs hooken und dann jeweils auch die Rücksprungadresse vom Stack loggen. Eventuell findest du ja darüber den Übeltäter. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Inwiefern können denn einem hier Profiler wie AqTime weiterhelfen? Sich mal ein paar Methoden rauspicken und schauen, wie viel Speicher bei Methodeneintritt und wie viel nach Verlassen noch da ist?
(Inwiefern das bei starkem Multithreading aussagekräftig sein kann?) |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
Christoph |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
- Es gibt einige Threadpools - Ein Pool holt einzelne Images von Netzwerkkameras via HttpRequest - Beim beenden des Jobs wird ein Objekt erzeugt in welchem ein TJpegImage und ein TBitmap32 erzeugt wird diese beiden Assignen das OriginalImage des HttpRequests. - Das Originalimage wird freigegeben. - Im Workerthread der Objekterkennung werden nun wilde Sachen gemacht. Am Ende werden die beiden erzeugten Objekte auch wieder freigegeben. Da kann es sowieso nicht liegen da es HD Bilder sind und der Effekt nur mit 64 Kameras im 3 Sekunden Intervall überhaupt in nützlicher Zeit erkennbar ist. In einem anderen Service logge ich den Gesamtspeicherverbrauch des betroffenen Services. Ich sehe das ein steigen des Memorys Z.B in fünf Minuten schrittweise von 86 auf 89MB. Dann nächste Messung 87 - nach 5 Minuten schrittweise auf 92. Nächste Messung 89.... So geht das rauf und runter. Nur in der Tendenz leider rauf. Zitat:
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
FastMM kann ja logischerweise nur Memory Manager interne Speicherreservierungen loggen, sprich: GetMem, FreeMem, New, Dispose und so weiter. Deshalb bin ich mir zu 99% sicher, dass irgendwo per WinAPI direkt Speicher alloziiert wird.
Es gibt doch bestimmt noch massenhaft "externe" Tools, welche die genannten WinAPIs überwachen und profilen können (Das vielleicht: ![]() |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Welche Windows Resourcen werden alloziiert? Google mal nach MemProof 0.948, das ist noch umsonst und könnte diesbezüglich Fragen beantworten (wenn FastMem das nicht macht)
Wäre es denkbar, das die Threads abbrechen und deshalb 'am Ende' keine Bilder freigegeben werden. Manchmal zumindest. Natürlich müsste man das in FastMem sehen, aber .... |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Leider scheinen weder WinLeak noch memproof mit dem 64bit Betriebssystem klarzukommen.
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Immer dieses 64bit :wall:
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Und jetzt? :|
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Ich habe per Zufall (vielleicht) etwas gefunden. Der Service läuft jetzt beim Kunden. Ich melde mich morgen wieder. Wenn es das war möchte ich dann von Euch wissen weshalb.
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
O.K. Das war ja einfach :roll: Das ist der Verusacher:
Delphi-Quellcode:
Muss ich das einfach wissen? Vermutlich würde auch ZeroMemory gehen? Diese Struktur ist als Record definiert. Und der Record wird der Funktion ShFileOperation als const übergeben. Üble Sache. Müssen Records grundsätzlich so behandelt werden? Oder nur mit Windows eigenen Funktionen?
procedure TDetectionCore.CopyPictures(PicFrom, PicTo: String);
function CopyFileEx(const ASource, ADest: string; ARenameCheck: boolean = false): boolean; var sh: TSHFileOpStruct; begin // so was hat offensichtlich gefehlt. Das war im Original nicht drin. {--->} FillChar(sh,SizeOf(sh),0); {<---} sh.wFunc := FO_COPY; sh.pFrom := PChar(ASource + #0); sh.pTo := PChar(ADest + #0); sh.fFlags := fof_Silent or fof_MultiDestFiles; if ARenameCheck then sh.fFlags := FOF_NOCONFIRMATION; Result:=ShFileOperation(sh)=0; end; begin FFileLock.Enter; Try if ForceDirectories(ExtractFilePath(PicTo)) then begin if not CopyFileEx(PicFrom, PicTo, True) then LogError('could not copy File:%s to:%s',[PicFrom,PicTo]); end else LogError('could not create directory: %s',[ExtractFilePath(PicTo)]); Finally FFileLock.Release; End; end; Nebenbei: Bevor ich auf das gekommen bin habe ich die Copyfunktion durch das ersetzt:
Delphi-Quellcode:
Gibt es da eine Präferenz bezüglich Geschwindigkeit oder anderen Gesichtspunkten das Eine oder das Andere zu nutzen?
var
mem: TMemoryStream; begin FFileLock.Enter; Try mem:= TMemoryStream.Create; if ForceDirectories(ExtractFilePath(PicTo)) then begin mem.LoadFromFile(PicFrom); mem.SaveToFile(PicTo); end Finally mem.Free; FFileLock.Release; End; Auf jeden Fall: Ich danke Euch vielmals für Eure Hinweise. Besonders nachdem FastMM zufrieden war hätte ich nicht weiter gewusst. Jetzt kann ich endlich aus dem Memory Loch wieder herauskriechen :-D Gruss Werner |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Wenn Du einen Record mit Werten belegst, dann musst Du alle Werte explizit belegen, ansonsten steht da doch Müll drin. Sehr unsauber. Das hier ein Speicherleck entsteht, hätte ich nicht gedacht, aber das es überhaupt funktioniert, wundert mich schon.
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Nebenbei:
Zitat:
Delphi-Quellcode:
sh.fFlags := sh.fFlags or FOF_NOCONFIRMATION;
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Was ich gerade gesehen habe: Der Record in der ShellApi ist so definiert:
Delphi-Quellcode:
Also pFrom und pTo sind WideChar. In der Funktion werden die aber als PChar gecastet. Ist das vielleicht nicht so gut?
_SHFILEOPSTRUCTW = record
Wnd: HWND; wFunc: UINT; pFrom: PWideChar; pTo: PWideChar; fFlags: FILEOP_FLAGS; fAnyOperationsAborted: BOOL; hNameMappings: Pointer; lpszProgressTitle: PWideChar; @DeddyH: Ja logisch - völliger Unsinn. @Dejan Vu: Keine Ahnung wie Du das meinst. pFrom und pTo sind Variablen eines Records. Was soll man da komplett(er) belegen? |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
In Delphi >= 2009 ist PChar ein PWideChar, davor war es PAnsiChar. In neueren Delphi-Versionen ist es für die Funktionalität also nicht von Bedeutung, allerdings unsauber IMO.
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Es ist völlig ok hier mit
Delphi-Quellcode:
zu arbeiten, denn es wird ja auch mit
PChar
Delphi-Quellcode:
und mit
TSHFileOpStruct
Delphi-Quellcode:
gearbeitet und eben nicht mit den expliziten Ansi oder Wide Varianten.
SHFileOperation
Hier wird je nach Compiler-Version automatisch zwischen der Ansi und Wide Variante gewechselt, genau so, wie auch
Delphi-Quellcode:
dann in der Bedeutung (
PChar
Delphi-Quellcode:
vs
PAnsiChar
Delphi-Quellcode:
) wechselt.
PWideChar
Es ist also nicht unsauber, sondern genau richtig! |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
Tipp: Da ich eh nicht weiß, wie ein bestimmter Parameterrecord deklariert ist, kopiere ich mir immer die Deklaration in meinen Code und belege dann alle Werte. Das ist viel einfacher, als zu überlegen, was man so alles braucht. Außerdem bin ich so auch gegen Veränderungen gewappnet, da der Programmierer nicht mehr nachschauen muss, welche Felder es denn so gibt. PS: Mit dem PWideChar wäre ich mir nicht so sicher (ist wohl abhängig -mal wieder- von der Delphiversion). In ![]() |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
@Dejan Vu:
Zitat:
@Sir Rufo: das ist aber nur dann genau richtig, wenn man nicht dynamische Typen/Funktionen mit statischen vermischt, also z.B. ShFileOperation mit dem _SHFILEOPSTRUCTW-Record aufruft. |
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
Zitat:
|
AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
@DeddyH
Ja das sollte schon klar sein und wurde hier ja auch nicht gemacht. Entweder alles automatisch oder alles fest, dann klappt es auch mit dem Nachbarn. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:47 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-2025 by Thomas Breitkreuz