pleriche / FastMM5

FastMM is a fast replacement memory manager for Embarcadero Delphi applications that scales well across multiple threads and CPU cores, is not prone to memory fragmentation, and supports shared memory without the use of external .DLL files.
283 stars 73 forks source link

FastMM5 and FireMonkey #47

Open westner opened 7 months ago

westner commented 7 months ago

Hallo,

I have a simple FMX-projecz (Win32) and try to use FastMM5 but it doesn't report leaks. Under VCL all works fine.

What's wronmg here?

program Project1;

uses FastMM5, Classes, FMX.Forms, FMX.Types, ;

{$R *.res}

begin FastMM5.FastMM_EnterDebugMode;

var l:=TStringlist.Create;

Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end.

pleriche commented 7 months ago

Hi,

You need to add either the backward compatible ReportMemoryLeaksOnShutdown := True; or the FastMM5 specific FastMM_MessageBoxEvents := FastMM_MessageBoxEvents + [mmetUnexpectedMemoryLeakSummary]; to the DPR.

Best regards, Pierre

westner commented 7 months ago

I did this already and it shows the memory leak but doesn't write a callstack to file. What have to be done to get a call stack in file which should be written to the same directory like the EXE?

pleriche commented 7 months ago

The FastMM_LogToFileEvents set controls which events are logged to file. The option you're looking for is mmetUnexpectedMemoryLeakDetail.

This will log the summary as well as the detail to the log file: FastMM_LogToFileEvents := FastMM_LogToFileEvents + [mmetUnexpectedMemoryLeakSummary, mmetUnexpectedMemoryLeakDetail];

You also need FastMM_FullDebugMode(64).dll either in the same folder as the executable or on the path in order to get stack traces.

westner commented 7 months ago

Now it works. Thanks. But why did I not need this in the past (old FastMM5)? Simple EnterDebugMode did the job?

Other question: I need a deeper callstack / stacktrace in to log. Could I increase it?

--------------------------------2024-02-16 16:05:21-------------------------------- A memory block has been leaked. The size is: 20

This block was allocated by thread 0x65C, and the stack trace (return addresses) at the time was: 00D30B37 [FastMM5.pas][FastMM5][FastMM_DebugGetMem$qqri][7863] 00D17242 [System.pas][System][@GetMem$qqri][4960] 00D18853 [System.pas][System][TObject.NewInstance][18324] 00D18F42 [System.pas][System][@ClassCreate$qqrpvzc][19654] 0123BA02 [FMX.Types.pas][FMX.Types][Types.TTabList.Create][4975] 00D4CDBA [System.SysUtils.pas][System.SysUtils][Sysutils.Supports$qqrxp14System.TObjectrx5_GUIDpv][28503] 00FF2184 [FMX.Controls.pas][FMX.Controls][Controls.TControl.GetTabList][5410] 00FE9F46 [FMX.Controls.pas][FMX.Controls][Controls.TControl.DoAddObject][2285] 01067024 [FMX.Controls.Presentation.pas][FMX.Controls.Presentation][Controls.Presentation.TPresentedControl.DoAddObject][595] 0123B5A7 [FMX.Types.pas][FMX.Types][Types.TFmxObject.DoInsertObject][4812] 012165A4 [System.Generics.Collections.pas][FMX.Platform.Win][Generics.Collections.%TDictionary__2$p23Fmx.Types.TWindowHandle43System.%DynamicArray$19System.Types.TRectF%%.GetBucketIndex$qqrxp23Fmx.Types.TWindowHandlei][7680] 00FEFD96 [FMX.Controls.pas][FMX.Controls][Controls.TControl.DoInsertObject][4361] 01067129 [FMX.Controls.Presentation.pas][FMX.Controls.Presentation][Controls.Presentation.TPresentedControl.DoInsertObject][639] 0123B447 [FMX.Types.pas][FMX.Types][Types.TFmxObject.InsertObject][4742] 00FF3CED [FMX.Controls.pas][FMX.Controls][Controls.TStyledControl.InternalApplyStyle][6180] 00FF33E4 [FMX.Controls.pas][FMX.Controls][Controls.TStyledControl.ApplyStyleLookup][5976] 00FED77B [FMX.Controls.pas][FMX.Controls][Controls.TControl.PrepareForPaint][3487] 01066E0E [FMX.Controls.Presentation.pas][FMX.Controls.Presentation][Controls.Presentation.TPresentedControl.ApplyStyleLookup][510] 00FF2B5C [FMX.Controls.pas][FMX.Controls][Controls.TStyledControl.PrepareForPaint][5742] 00FED71E [FMX.Controls.pas][FMX.Controls][3485]

The block is currently used for an object of class: FMX.Types.TTabList

The allocation number is: 331440

Current memory dump of 28 bytes starting at pointer address B444700: 38 65 22 01 F0 F1 A2 05 00 DE 53 0B 94 64 22 01 00 00 00 00 00 9A 2D FE 37 0B D3 00 8 e " . . . . . . . S . . d " . . . . . . . - . 7 . . . --------------------------------2024-02-16 16:05:21--------------------------------

westner commented 7 months ago

And a second question:

My DPR looks like:

begin FastMM5.FastMM_EnterDebugMode; ReportMemoryLeaksOnShutdown := True; FastMM_LogToFileEvents := FastMM_LogToFileEvents + [mmetUnexpectedMemoryLeakSummary, mmetUnexpectedMemoryLeakDetail];

var l:=TStringlist.Create;

Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end.

The memory leak of the string lsit is reported

--------------------------------2024-02-16 16:05:21-------------------------------- A memory block has been leaked. The size is: 76

This block was allocated by thread 0x65C, and the stack trace (return addresses) at the time was: 00D30B37 [FastMM5.pas][FastMM5][FastMM_DebugGetMem$qqri][7863] 00D17242 [System.pas][System][@GetMem$qqri][4960] 00D18853 [System.pas][System][TObject.NewInstance][18324] 00D18F42 [System.pas][System][@ClassCreate$qqrpvzc][19654] 00DDB228 [System.Classes.pas][System.Classes][Classes.TStringList.Create][8121] 00D3225D [FastMM5.pas][FastMM5][FastMM_SetNormalOrDebugMemoryManager$qqrv][10183] 01327D58 75597BA9 [BaseThreadInitThunk] 76F4BD2B [Unknown function at RtlInitializeExceptionChain] 76F4BCAF [Unknown function at RtlClearBits]

The block is currently used for an object of class: System.Classes.TStringList

The allocation number is: 1

Current memory dump of 84 bytes starting at pointer address 5A7AEC0: E4 CE DA 00 00 00 00 00 80 67 B6 05 4C D0 AD 05 00 00 00 00 00 00 00 00 2C 00 22 00 3D 00 0E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9B 16 98 8B 37 0B D3 00 . . . . . . . . . g . . L . . . . . . . . . . . , . " . = . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 . . .

but one line is empty. I assumed that this should be the linke in my DPR.

Why is this not outputted? Why is my code not in the stack trace?

My settings looks like:

grafik

grafik

pleriche commented 7 months ago

But why did I not need this in the past (old FastMM5)? Simple EnterDebugMode did the job? My guess would be that you had some of the FastMM4 defines set - FastMM5 is backwards compatible with the FastMM4 defines.

I need a deeper callstack / stacktrace in to log. Could I increase it? You can set the number of stack trace entries via FastMM_SetDebugModeStackTraceEntryCount.

The missing unit and line info for calls from the DPR seems to be an issue with the JCL map file parser. When using the .map file I see this: 00881E7D [FastMM5.pas][FastMM5][FastMM_SetNormalOrDebugMemoryManager$qqrv][10183] 00D8DB50 76FAFCC9 [BaseThreadInitThunk]

But when I embed JCL debug info into the executable I see this: 003A1E7D [FastMM5.pas][FastMM5][FastMM_SetNormalOrDebugMemoryManager][10183] 008ADB50 [Project3][Project3][18] 76FAFCC9 [BaseThreadInitThunk]

Usually there's not a lot of code in the DPR, so I don't think this is a serious issue. However, if it is a problem for you you can install the JCL debug expert package and have it inject JDBG info into your executable. As an added advantage then you also do not need to ship the .map file with the executable.