Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   FastMM Memory Leaks : Lesen und verstehen von Stacktrace (https://www.delphipraxis.net/181767-fastmm-memory-leaks-lesen-und-verstehen-von-stacktrace.html)

taveuni 8. Sep 2014 12:17

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:
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 @  . ‰  _  @  .
Es scheint sich um eine generische Liste zu handeln. Aber wo ist springende Punkt um welche Liste/Funktion es sich handelt?
Oder hier:
Code:
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 @  . ‰  _  @  .
Es sind hier uDetection.pas und uDataStorage.pas aufgeführt.

Code:
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 €  €  €  €  . . . . ±  . Þ  ~
Hier wird sogar das Objekt: TObjectSensor aufgeführt und drei units welche von uns sind.
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.

Der schöne Günther 8. Sep 2014 12:36

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:
unit Unit2;

interface
   procedure createLeak(); forward;

implementation

procedure createLeak();
begin
   TObject.Create();
end;

end.
erzeugt folgende Ausgabe:
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
  • Unit2.pas
  • Die Methode createLeak
  • Zeile 10

Das wird nie freigegeben.

taveuni 8. Sep 2014 12:44

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?

nuclearping 8. Sep 2014 12:51

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Wenn du in deiner DPR ...

Delphi-Quellcode:
program ...;

uses
  ...;

begin
  ReportMemoryLeaksOnShutdown := TRUE;

  ...
end.
... schreibst, solltest beim Beenden des Programms eine entsprechende Meldung erhalten.

taveuni 8. Sep 2014 13:11

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.

pertzschc 8. Sep 2014 13:38

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

mjustin 8. Sep 2014 13:43

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von taveuni (Beitrag 1271594)
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?

Ja, indem man den aktuellen Status des FastMM4 Speichermanagers in eine Datei schreibt und diese beobachtet.
Objekte, die leaken, erscheinen dann mit einer stetig wachsenden Anzahl in der Liste.

How do I find memory leaks at run time with FastMM4?
http://mikejustin.wordpress.com/2013...-with-fastmm4/

Strategy or tools to find “non-leak” memory usage problems in Delphi?
http://stackoverflow.com/a/17365483/80901

Step by step Anleitung:

  1. add a call to LogMemoryManagerStateToFile('memory.log', '') in a place where it will be called in intervals
  2. run the application
  3. open the log file with an editor (which auto-refreshes when the file content changes)
  4. watch the first lines of the file, they will contain the memory allocations which occupy the highest amount of memory
  5. if you see a class or memory type constantly has a growing number of instances, this can be the reason of your leak

taveuni 8. Sep 2014 13:46

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von mjustin (Beitrag 1271619)

Ja, indem man den aktuellen Status des FastMM4 Speichermanagers in eine Datei schreibt und diese beobachtet.
Objekte, die leaken, erscheinen dann mit einer stetig wachsenden Anzahl in der Liste.

Danke! Das werd ich versuchen und mich wieder melden.

sahimba 8. Sep 2014 13:58

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von taveuni (Beitrag 1271594)
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?

Hoffe, jetzt flamed niemand wegen Werbung... mein Tool "DDDebug" kann das recht elegant. http://ddobjects.de/dddebug
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.

taveuni 8. Sep 2014 14:08

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.

sahimba 8. Sep 2014 14:11

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Hallo.

Zitat:

Zitat von taveuni (Beitrag 1271628)
Hallo Sahimba,
Ich hab mir Dein Tool schon angesehen.

Das freut mich. Weisst Du, wann das war - vll. war es eine ältere Version?! (Der Preis wurde zwischenzeitlich gesenkt...)
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.

Dejan Vu 8. Sep 2014 14:22

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Eigentlich ist es mir (erstmal) egal wenn beim beenden des Programms ein Objekt welches beim Start erzeugt wurde nicht freigegeben wird.
Das sollte es aber nicht. Räum doch erst einmal deinen Code so auf, das alle Objekte weitestgehend sauber freigegeben werden. Auch wenn es eigentlich überflüssig ist, aber erstens ist das sauberer und zweitens ist dann die Suche nach den Leaks viel einfacher

nuclearping 8. Sep 2014 14:43

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von taveuni (Beitrag 1271612)
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.

Es ging darum:
Zitat:

Zitat von taveuni (Beitrag 1271594)
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?

Damit bekommst du zwar nicht zur Laufzeit eine Meldung, aber beim Beenden müsste er dir sowas wie das hier anzeigen:

http://download.jam-software.de/tree...g_mem_leak.png

sahimba 8. Sep 2014 15:37

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von nuclearping (Beitrag 1271639)
Damit bekommst du zwar nicht zur Laufzeit eine Meldung, aber beim Beenden müsste er dir sowas wie das hier anzeigen

Es gibt durchaus, und das ist gar nicht so selten, Fälle, in denen der Speichebedarf stetig wächst, Objekte in irgendwelchen Listen gehalten werden, die dann, gemeinsam mit den referenzierten Objekten, erst bei Programmbeendigung freigegeben werden. Das sind dann ja keine Speicherleaks im klassischen Sinne und es wrd Dir nichts angezeigt.

nuclearping 8. Sep 2014 16:55

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.

taveuni 15. Sep 2014 07:53

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:

Zitat von sahimba (Beitrag 1271647)
Es gibt durchaus, und das ist gar nicht so selten, Fälle, in denen der Speichebedarf stetig wächst, Objekte in irgendwelchen Listen gehalten werden, die dann, gemeinsam mit den referenzierten Objekten, erst bei Programmbeendigung freigegeben werden. Das sind dann ja keine Speicherleaks im klassischen Sinne und es wrd Dir nichts angezeigt.

Ich bin nun ein bisschen weiter - trotzdem bin ich nun noch verwirrter. Mit Hilfe der FastMM Dateien und Deines DDDebug konnte ich nun den Service so kompilieren dass alle Objekte welche erzeugt werden beim beenden auch wieder freigegeben werden. Somit erhalte ich beim beenden keine Meldung mehr von FastMM.Soweit so gut. Aber: Vor Ort habe ich jetzt einen Service mit Debug kompiliert und der läuft mit der FastMM DLL im FullDebugMode. Ich rufe darin auch zyklisch "LogMemoryManagerStateToFile" auf um die Anzahl Objekte und den Speicherverbrauch zu loggen. Konkret ist es so: Ich starte den Service, der Memory Report sieht so aus (den Rest des Logs habe nicht kopiert da dieser identisch ist):
Code:
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
Nach vier Tagen sieht der Report so aus:
Code:
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
Und wenn ich den Service beende - keine Meldung von FastMM! Also eigentlich alles super oder?
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?

Der schöne Günther 15. Sep 2014 09:17

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?

taveuni 15. Sep 2014 09:21

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.

baumina 15. Sep 2014 09:30

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Nur mal so überlegt:

Delphi-Quellcode:
procedure TForm1.Timer1OnTimer(Sender: TObject);
var
  SpeicherFresser : TEdit;

begin
  Speicherfresser := TEdit.Create(self);
end;
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.

taveuni 15. Sep 2014 09:33

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von baumina (Beitrag 1272601)
Nur mal so überlegt:

Delphi-Quellcode:
procedure TForm1.Timer1OnTimer(Sender: TObject);
var
  SpeicherFresser : TEdit;

begin
  Speicherfresser := TEdit.Create(self);
end;
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.

Einverstanden. Aber dann müsste die Anzahl Instanzen im memory.log von FastMM doch hochgezählt werden. Und das ist eben nicht der Fall!

Zacherl 15. Sep 2014 09:47

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von taveuni (Beitrag 1272599)
Dann könnten es höchstens Windows DLL's sein. Andererseits - wohl kaum? Hmhh.. Ich bin ratlos.

Wäre für mich aber auch die einzige Erklärung. Gibt, selbst wenn man von den direkten Varianten (VirtualAlloc, LocalAlloc, GlobalAlloc, HeapAlloc, etc.) absieht, enorm viele WinAPIs, die Speicher alloziieren können.

Bei MSDN-Library durchsuchenFormatMessage mit dem FORMAT_MESSAGE_ALLOCATE_BUFFER Flag muss man am Ende beispielsweise selbst einmal LocalFree callen.

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.

Der schöne Günther 15. Sep 2014 09:52

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?)

pertzschc 15. Sep 2014 10:00

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von taveuni (Beitrag 1272602)
Einverstanden. Aber dann müsste die Anzahl Instanzen im memory.log von FastMM doch hochgezählt werden. Und das ist eben nicht der Fall!

Kannst Du den Quellcode Deines Service posten? Irgendwo passiert es dort, auch wenn der FastMM es nicht mitbekommt. Oder wie vermutet ausserhalb (DLL)...
Christoph

taveuni 15. Sep 2014 10:18

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von pertzschc (Beitrag 1272606)
Kannst Du den Quellcode Deines Service posten? Irgendwo passiert es dort, auch wenn der FastMM es nicht mitbekommt. Oder wie vermutet ausserhalb (DLL)...
Christoph

Leider nein. Auszüge davon ja - aber das ist sowieso sinnfrei. Glaubst Du - Du könntest nur durch Code Review das Problem erkennen? Ich habe schon mehrere meiner Meinung nach kritische Vorgänge isoliert (so a la Unittest) und diese unabhängig getestet. Ohne Ergebnis. Grob umrissen läuft es so:
- 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:

Zitat von Zacherl (Beitrag 1272603)
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.

Leider momentan (noch) nicht. Kann es sein dass ich mit AQ Time weiterkäme? Wobei das ja preislich für dieses eine Ding.. Andererseits wenn ich Tage und Wochen aufwende....

Zacherl 15. Sep 2014 10:24

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: http://winleak.sourceforge.net/).

Dejan Vu 15. Sep 2014 10:26

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 ....

taveuni 15. Sep 2014 12:25

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Leider scheinen weder WinLeak noch memproof mit dem 64bit Betriebssystem klarzukommen.

Dejan Vu 15. Sep 2014 13:55

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Immer dieses 64bit :wall:

Der schöne Günther 15. Sep 2014 15:47

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Und jetzt? :|

taveuni 15. Sep 2014 15:52

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.

taveuni 16. Sep 2014 06:57

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
O.K. Das war ja einfach :roll: Das ist der Verusacher:
Delphi-Quellcode:
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;
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?

Nebenbei: Bevor ich auf das gekommen bin habe ich die Copyfunktion durch das ersetzt:
Delphi-Quellcode:
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;
Gibt es da eine Präferenz bezüglich Geschwindigkeit oder anderen Gesichtspunkten das Eine oder das Andere zu nutzen?

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

Dejan Vu 16. Sep 2014 07:15

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.

DeddyH 16. Sep 2014 07:22

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Nebenbei:
Zitat:

Delphi-Quellcode:
sh.fFlags := fof_Silent or fof_MultiDestFiles;
  if ARenameCheck then
    sh.fFlags := FOF_NOCONFIRMATION;

Ist das wirklich so gewollt, dass die gerade gesetzten Flags wieder überschrieben werden? Oder soll FOF_NOCONFIRMATION ggf. hinzugefügt werden? In dem Fall müsste es heißen:
Delphi-Quellcode:
sh.fFlags := sh.fFlags or FOF_NOCONFIRMATION;

taveuni 16. Sep 2014 07:26

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Was ich gerade gesehen habe: Der Record in der ShellApi ist so definiert:
Delphi-Quellcode:
 _SHFILEOPSTRUCTW = record
    Wnd: HWND;
    wFunc: UINT;
    pFrom: PWideChar;
    pTo: PWideChar;
    fFlags: FILEOP_FLAGS;
    fAnyOperationsAborted: BOOL;
    hNameMappings: Pointer;
    lpszProgressTitle: PWideChar;
Also pFrom und pTo sind WideChar. In der Funktion werden die aber als PChar gecastet. Ist das vielleicht nicht so gut?

@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?

DeddyH 16. Sep 2014 07:38

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.

Sir Rufo 16. Sep 2014 07:55

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Es ist völlig ok hier mit
Delphi-Quellcode:
PChar
zu arbeiten, denn es wird ja auch mit
Delphi-Quellcode:
TSHFileOpStruct
und mit
Delphi-Quellcode:
SHFileOperation
gearbeitet und eben nicht mit den expliziten Ansi oder Wide Varianten.

Hier wird je nach Compiler-Version automatisch zwischen der Ansi und Wide Variante gewechselt, genau so, wie auch
Delphi-Quellcode:
PChar
dann in der Bedeutung (
Delphi-Quellcode:
PAnsiChar
vs
Delphi-Quellcode:
PWideChar
) wechselt.

Es ist also nicht unsauber, sondern genau richtig!

Dejan Vu 16. Sep 2014 07:56

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von taveuni (Beitrag 1272696)
@Dejan Vu: Keine Ahnung wie Du das meinst. pFrom und pTo sind Variablen eines Records. Was soll man da komplett(er) belegen?

Wie wäre es damit, *alle* Felder des Records explizit mit definierten Werten zu belegen? Wo werden denn im Code die Felder Wnd, fAnyOperationsAborted, hNameMappings und lpszProgressTitle gesetzt? Letzteres muss man wohl bei deiner Konstellation nicht belegen, aber unsauber ist es schon, da bei Änderung der Parmeter der Title doch eine Rolle spielen könnte. Nicht in diesem Kontext, aber bei Copy&Paste spielt das schon eine Rolle. Und das das negative Folgen haben kann, einige Werte undefiniert zu lassen, hat man ja wohl gesehen.

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 MSDN sind die Felder als 'LPCTSTR' deklariert, was einem PAnsiChar entspricht, denke ich.

DeddyH 16. Sep 2014 08:03

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
@Dejan Vu:
Zitat:

Delphi-Quellcode:
FillChar(sh,SizeOf(sh),0);

Damit wird der komplette Record mit Nullen befüllt, was soll er denn noch machen?

@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.

taveuni 16. Sep 2014 08:06

AW: FastMM Memory Leaks : Lesen und verstehen von Stacktrace
 
Zitat:

Zitat von DeddyH (Beitrag 1272700)
Zitat:

Delphi-Quellcode:
FillChar(sh,SizeOf(sh),0);

Damit wird der komplette Record mit Nullen befüllt, was soll er denn noch machen?

Das habe ich (eigentlich wars nicht ich) aber eben vorher genau nicht gemacht! Und da ist dann das Memory gestiegen. Mit dem FillChar nicht mehr. Meine Frage ist nun: Weshalb muss das gemacht werden? Und: Muss dass in Delphi eigenen Funktionen wo Records (notabene als const) übergeben werden ebenfalls gemacht werden?

Sir Rufo 16. Sep 2014 08:07

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 12:00 Uhr.
Seite 1 von 2  1 2      

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