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

AccessViolation with fastmm5 #31

Closed Zeus64 closed 2 years ago

Zeus64 commented 2 years ago

When you run this simple project with fastMM5 it's crash after clicking on the button1 and then clicking anywhere on the form. Without FastMM5 it's run very well

The demo below (do not afraid if many units, I just copy past the source code of Alcinoe in it) :

https://www.amazon.com/clouddrive/share/zoHGrx6G14GQekO7pYf73fLcOAPzCerncgW9bF6YTxW

pleriche commented 2 years ago

Hi,

Compilation fails with this error: [dcc32 Fatal Error] ALCommon.pas(18): F1026 File not found: 'Alcinoe.inc'

What you're most likely facing here is a case of survivorship bias: Presumably you developed the application using FastMM4 (the default RTL memory manager), and the bugs that showed symptoms were fixed. The bug(s) that remain don't show any obvious symptoms with FastMM4 through pure happenstance, but as soon as you use a memory manager that uses a different memory layout then suddenly these start showing symptoms as well. It is important that these be fixed, because even if you stick to the old memory manager then a seemingly unrelated change in another part of the application could cause these to start showing symptoms.

If you add the missing file I'll take a look at the test case for you. If you want to try to find the issue yourself first, I suggest you enable debug mode by calling FastMM_EnterDebugMode in the startup code. I'm not normally a betting man, but I reckon there's a very good chance that'll expose the problematic code.

pleriche commented 2 years ago

I got the include file from your repository. When running the test application with debug mode enabled I get an A/V with read at address $80808088. $80 is the fill pattern of freed blocks in debug mode, so this tells me it is a case of an object being used after it was freed.

It looks like things go wrong while destroying child controls of the TALCustomScrollBox. It is when it tries to free the second child control of the TALCustomScrollBox that it accesses an object that has already been freed. I have not looked very deeply into the code, but my suspicion is that there is a control ownership issue.

Zeus64 commented 2 years ago

Hi Pierre,

I work on it, it's really strange this morning on my main project I still have the error, but not anymore on the demo I sent you (I have another error but not because of fastmm). The only think I did from yesterday it's closing and reopening Delphi. Happy that you saw the error so you can believe me :) The error is raise in the RTL when it's try to free an Interface stored in TabList property of each component: TList:Icontrol

I try grab more info, first to reproduce it "again" in the demo project

pleriche commented 2 years ago

That is the nature of these kinds of bugs. You do not have control over the content of the block after it has been freed, so it could contain anything. Some random content may cause the A/V and other content not.

If you want the best chance to reproduce the crash reliably, you should enable debug mode so that freed blocks are filled with the $80 pattern. If you do that you should see the crash regardless of whether you're using FastMM4 or FastMM5.

Zeus64 commented 2 years ago

Yes 👍 with the debug mode enabled I can reproduce the error. I try on fastmm4 with also debugmode enabled then i have :


Project7.exe: Memory Error Detected

FastMM has detected an attempt to use an interface of a freed object. An access violation will now be raised in order to abort the current operation.

The current thread ID is 0x8074, and the stack trace (return addresses) leading to this error is:

40EEF7 [System.pas][System][@IntfClear$qqrr44System.%DelphiInterface$17System.IInterface%][38798]
40BFA6 [System.pas][System][@FinalizeArray$qqrpvt1ui][33303]
44D0DF [System.Generics.Collections.pas][System.Generics.Collections][Generics.Collections.TListHelper.InternalDeleteRangeMRef][3395]
77A788F6 [Unknown function at RtlAllocateHeap]
44CBF1 [System.Generics.Collections.pas][System.Generics.Collections][Generics.Collections.TListHelper.InternalDeleteRange4][3264]
44CC3B [System.Generics.Collections.pas][System.Generics.Collections][Generics.Collections.TListHelper.InternalDeleteRange4][3272]
44CBF1 [System.Generics.Collections.pas][System.Generics.Collections][Generics.Collections.TListHelper.InternalDeleteRange4][3264]
44CC3B [System.Generics.Collections.pas][System.Generics.Collections][Generics.Collections.TListHelper.InternalDeleteRange4][3272]
44CBF1 [System.Generics.Collections.pas][System.Generics.Collections][Generics.Collections.TListHelper.InternalDeleteRange4][3264]
44CC3B [System.Generics.Collections.pas][System.Generics.Collections][Generics.Collections.TListHelper.InternalDeleteRange4][3272]
77A788F6 [Unknown function at RtlAllocateHeap]

so it's just look that the error was always here but "hidden" on the fastmm included in Delphi because full debug mode was not enabled. As this error seam to be in delphi RTL i try to dig a little more in it now

Zeus64 commented 2 years ago

Ok I found and corrected the bug, was not at all with FastMM5, in opposite I will say that FastMM5 help me to point that a problem was here! Sadly the fastMM version included in delphi never raise any exception (even with reportmemoryleaksonshuntdown activated). Thanks a lot @pleriche for your help.

Is their with fastMM5 some options like in fastmm4 "CatchUseOfFreedInterfaces" to detect use of freed memory ? how in fastMM5 activate correctly all options to detect access to freed memory, memory leak, stack trace of memory leak, etc. So what options to activate in debug to fully check everything as possible ?

pleriche commented 2 years ago

CatchUseOfFreedInterfaces is not implemented in FastMM5. The reason for that is that if you enable it then blocks cannot be filled with the $80 debug pattern, and other issues can thus be missed. CatchUseOfFreedInterfaces really only gives you a more meaningful error message when using an interface of a freed object, you'll still get a crash without it, it'll just be an A/V. Either way, the stack trace should tell you where things went wrong.

To enter debug mode in FastMM5 you call FastMM_EnterDebugMode. This is very similar to the FullDebugMode of v4.

Take a look at FastMM_MessageBoxEvents to see which events can be reported via a popup message. The leak report is one such event. You can also log events to file via FastMM_LogToFileEvents.

I try to include all the required documentation in the source file, so if you open FastMM5.pas and you scan through the interface section you'll see all the various options and a description of what each does.

Zeus64 commented 2 years ago

Thanks a lot @pleriche! Wonderfull work!