RussellW 3 Posted March 19, 2019 I have an application using IOmniBackgroundWorker and I'm using ScaleMM2. I had a memory leak issue in the interfaced object passed to the WorkItem and while that existed I had no issues when I shut down the application. However, having fixed that issue (circular Interface issue fixed by declaring the field as [weak]) I now get a runtime error when I shut down the application. If I use the standard Delphi Memory Manager I don't get this exception. Any ideas about tracking this down? Share this post Link to post
Микола Петрівський 10 Posted March 20, 2019 Try FastMM4 in FullDebugMode. Probably some code tries to call interface method, but reference is nil. Share this post Link to post
RussellW 3 Posted March 22, 2019 Ok, I'll try that but I'm not getting the issue with FastMM Share this post Link to post
Primož Gabrijelčič 223 Posted March 22, 2019 Try to minimize the problem. Extract the problematic code from the application and try to reproduce. Or disable parts of the code which could relate to the problem and check if it went away. Share this post Link to post
RussellW 3 Posted March 22, 2019 with FastMM4 I got a 'FreeMem called after FastMM uninstalled' Share this post Link to post
Allen@Grijjy 44 Posted March 22, 2019 In my experience and tests, the latest FastMM4 has various leak related issues, some of them are quite bad with the newer versions of Delphi that don't exist with the built-in memory manager which is also a subset of FastMM. Most of the memory managers haven't been actively worked on in years and I doubt their ability to properly handle many scenarios. Share this post Link to post
Primož Gabrijelčič 223 Posted March 22, 2019 FastMM4 works perfectly and has no leaks as far as I know. We are using FastMM4 in Delphi applications that run 24/7 for years at the time and it works just fine. That holds for the latest FastMM from https://github.com/pleriche/FastMM4. I have no idea how built-in FastMM works. One should just be careful when running FastMM4 with /dFullDebugMode. In this mode, FastMM never returns memory to the operating system and your code can run out of memory. This is a feature, not a bug. 1 Share this post Link to post
RussellW 3 Posted March 22, 2019 Interesting. This error occurs with FastMM4, BrainMM and ScaleMM2 but not with the FastMM default in Delphi. However, at the end of the ScaleMM2 pas file there is this: finalization {$if CompilerVersion < 23} // issue 6: Delphi XE2 has annoying bug when using SetLocaleOverride -> AV in finalization of System.pas due to freemem(PreferredLanguagesOverride) // So in case of Delphi XE and lower, we use the normal method ScaleMMUninstall; {$ifend} Now if I call ScaleMMUninstall irrespective of Compiler (in this case I'm using Tokyo) then my runtime error when the app is closed goes away. Share this post Link to post
Stefan Glienke 2019 Posted March 22, 2019 (edited) The problem is not any 3rd party MM but the fact that some pieces in the RTL are deallocated within System.pas finalization which takes place after detaching/finalizing any 3rd party MM (if that one does something in its finalization block as posted in the previous post). And then it tries to give back memory to the system that it orginally had from the already unloaded/detached 3rd party MM. There are various fixes in the RTL (I don't remember which version they did that in) that use SysGetMem/SysFreeMem to bypass the pluggable memory manager API. It can very well be the case they missed something or you are using a version that does not have them yet. Edited March 22, 2019 by Stefan Glienke 1 Share this post Link to post
Allen@Grijjy 44 Posted March 22, 2019 (edited) 20 minutes ago, Stefan Glienke said: The problem is not any 3rd party MM but the fact that some pieces in the RTL are deallocated within System.pas finalization which takes place after detaching/finalizing any 3rd party MM Out of curiosity, what are you all using to determine you are leaking or not? Let's assume we ignore System.pas related things. Have you compared the results of a tool like the Deleaker using the base memory manager with a large project vs. Deleaker with FastMM4 enabled (without full debug mode) or any other memory manager? Edited March 22, 2019 by Allen@Grijjy minor Share this post Link to post
Allen@Grijjy 44 Posted March 22, 2019 (edited) Attached is the smallest example I could make of a leak (it leaks roughly 1MB) that only occurs in FastMM4 (latest edition) with FullDebugMode disabled but does not occur with the default memory manager of Delphi 10.3. To test it, just compare it with FastMM4 commented/uncommented in the .dpr. You will need some external leak analysis tool like this one, for example, https://www.deleaker.com I honestly would like to understand what is happening here because I have also used FastMM over the years in numerous projects, but I found a few issues like this one and a couple of others related to reference counted interface de-allocations. Note: I am aware that FastMM4's leak checker doesn't show any leaks, but like I said previously, I don't trust it to analyze itself. LeakExample.zip Edited March 22, 2019 by Allen@Grijjy Share this post Link to post
RussellW 3 Posted March 22, 2019 I use MadExcept for in app leak checking. I seem to get them on TMemIniFile a bit. Share this post Link to post
Stefan Glienke 2019 Posted March 22, 2019 (edited) FastMM4 FullDebug in a debug build of our application - LeakCheck in unit and integration tests If any third party leak analysis tool claims that FastMM has a memory leak it probably will tell you the call stack of where it comes from and you will be able to find it. Also are you aware that there is RegisterExpectedMemoryLeak function that the third party tool might not be aware of and has a false positive? As for Deleaker - I think that tool and me won't become friends. UI is irritating and if its burning 100% of my CPU for minutes while triggering a million werfault.exe processes that it supresses until I press cancel to find some memory allocation leaks from that simple program I can't imagine what it will do when I let it run for a real application. "Sorry, but's a no from me" Edited March 22, 2019 by Stefan Glienke 1 Share this post Link to post
Allen@Grijjy 44 Posted March 22, 2019 (edited) 3 hours ago, Stefan Glienke said: If any third party leak analysis tool claims that FastMM has a memory leak it probably will tell you the call stack of where it comes from and you will be able to find it. Also are you aware that there is RegisterExpectedMemoryLeak function that the third party tool might not be aware of and has a false positive? The example I made is trivial. It expands a queue, so the size of the leak is directly proportional to the number of records you en-queue. Even if you destroy the queue, the leak persists. I am aware of RegisterExpectedMemoryLeak function. The call stack shows the problem comes from the Collections.TListHelper.InternalSetCapacity in Delphi's collections unit, that eventually calls the ReallocMem routine: LeakExample.exe!@ReallocMem$qqrrpvi Line 4900 004070b8 LeakExample.exe!DynArraySetLength$qqrrpvpvipi Line 35920 + 0x5 bytes 0040c466 LeakExample.exe!Generics.Collections.TListHelper.InternalSetCapacity Line 4489 + 0x9 bytes 004eb6f1 In the example I provided the actual collection is a queue of records that is created and destroyed. However when the queue grows, FastMM internally calls FastReallocMem to expand and internally determines it's a large block reallocation. If I simply redirect the ReallocMem routine back to SysReallocMem inside of FastMM, everything deallocates properly. Like you said, it could be a flaw in this tool, but the problem doesn't happen with Delphi's built in memory manager. It also doesn't happen if I change FastMM's source to simply call SysReallocMem immediately upon calling FastReallocMem. It also doesn't happen with numerous other data types, just collections, specifically queues of records. Edited March 22, 2019 by Allen@Grijjy 1 Share this post Link to post
RussellW 3 Posted March 29, 2019 I have just tried my app (64Bit, 16 threads) with ScaleMM2 again, and get this exception on the first batch I run, but not on shutdown as the app is still running: exception number : 1 exception class : EInvalidPointer exception message : Invalid pointer operation. main thread ($163c): 0041ecf3 +053 PlustNetProcess.LeakTest2.exe smmLargeMemory 125 +13 TLargeMemThreadManager.FreeMem 013f6c57 +087 PlustNetProcess.LeakTest2.exe DSiWin32 6175 +15 DSiClassWndProc 7ffa03bf +000 user32.dll DispatchMessageW 007d206e +12e PlustNetProcess.LeakTest2.exe Vcl.Forms TApplication.ProcessMessage 007d20e3 +013 PlustNetProcess.LeakTest2.exe Vcl.Forms TApplication.HandleMessage 007d2531 +0e1 PlustNetProcess.LeakTest2.exe Vcl.Forms TApplication.Run 01fb3e27 +147 PlustNetProcess.LeakTest2.exe PlustNetProcess 116 +17 initialization 7ffa0379 +020 KERNEL32.DLL BaseThreadInitThunk 7ffa058f +032 ntdll.dll RtlUserThreadStart I tried IntelTBB (Single allocated thread) and got an AV on closedown as did BrainMM and FastMM. The only one that doesn't is the one that ships with Delphi, which doesn't give me the speed that is needed. Any ideas? I guess I could try a simple threaded app to see if that throws up anything. Share this post Link to post
RussellW 3 Posted March 29, 2019 The FastMM4 raises the error as a call to a memory function after FastMM4 has been unloaded. There is an option in the inc file to not raise that. Share this post Link to post
Микола Петрівський 10 Posted April 3, 2019 Usually, you should not call memory-related functions after MM unloading. There is a bug somewhere. Maybe FastMM4 is not the first in uses clause, or something gets uninitialized too late. Share this post Link to post