RegisterExpectedMemoryLeak
RegisterExpectedMemoryLeak
I'm a bit hazy on the relationship between MadExcept's memory leak reporting and FastMM4. FastMM has the routine RegisterExpectedMemoryLeak to announce known or innocuous memory leaks so that reports aren't generated if there are no memory leaks apart from those ones.
Is there an equivalent function in ME? (I can't search for "RegisterExpectedMemoryLeak" - it's too long!).
Can I still use the FastMM one (it doesn't seem to work)?
Thanks,
R
Is there an equivalent function in ME? (I can't search for "RegisterExpectedMemoryLeak" - it's too long!).
Can I still use the FastMM one (it doesn't seem to work)?
Thanks,
R
Re: RegisterExpectedMemoryLeak
madExcept has a function called "ThisIsNoLeak()". See here:
http://help.madshi.net/madExceptUnit.htm#ThisIsNoLeak
http://help.madshi.net/madExceptUnit.htm#ThisIsNoLeak
Re: RegisterExpectedMemoryLeak
Thanks Mathias, The FastMM version can be called with a class identifier and count, e.g.:
which allows 3 instances of TBitmap to be allocated and not freed without complaint. Being able to specify the memory leaks by class is useful because it means I don't have find where they occur, and I don't need to modify the source where they occur, which is better when it is in a library.
For example, I know that Indy leaks a TIdThreadSafeInteger and 2 of TIdCriticalSection each time my app runs, but this is known about and inconsequential - so I have this at the start of my main program:
How would I use ThisIsNoLeak to suppress the report here? Do you support this? (or plan to?).
Code: Select all
RegisterExpectedMemoryLeak (TBitmap, 3) ;
For example, I know that Indy leaks a TIdThreadSafeInteger and 2 of TIdCriticalSection each time my app runs, but this is known about and inconsequential - so I have this at the start of my main program:
Code: Select all
RegisterExpectedMemoryLeak (TIdThreadSafeInteger, 1) ;
RegisterExpectedMemoryLeak (TIdCriticalSection, 2) ;
Re: RegisterExpectedMemoryLeak
This is currently not supported. It's not a bad idea, but I'm wondering how it would work if there are real leaks with the same class? E.g. what happens if there are 4 TBitmap leaks? Are all 4 shown then? Or are the "first" 3 ignored?
Re: RegisterExpectedMemoryLeak
I guess that you could expect any memory leaked in this fashion would likely be allocated in the a library unit initialisation, i.e. before your program had started allocating memory. So if you had
you could store the class identifying info and a counter which you would initialise to 4. Every time a TBitmap is allocated the counter would be decremented and when the counter reaches zero assume that all of the class instances that need to be ignored have been allocated and start logging that class from then on. It wouldn't be foolproof but would still be useful in a lot of cases.
Code: Select all
ThisIsNoLeak (TBitmap, 4) ;
Re: RegisterExpectedMemoryLeak
Wouldn't it be more useful to hide the expected leaks only if there are no additional leaks, and to show all 4 TBitmap leaks, if there are more than expected? I fear that when there are 4 leaks instead of the expected 3, we can't know for sure if the expected leaks are really the first 3. They might be in most cases, but that doesn't always have to be true. If it's not true, we would actually see one expected leak and the real leak would be hidden...
Re: RegisterExpectedMemoryLeak
Yes indeed. In fact that's exactly how FastMM does it. If the only memory leaks it detects are ones notified to it, you don't get any report, otherwise you get all leaks reported.
Re: RegisterExpectedMemoryLeak
Ok, I'll add this to my to do list.
Re: RegisterExpectedMemoryLeak
Implemented in this build:
http://madshi.net/madCollectionBeta.exe (installer 2.7.7.15)
http://madshi.net/madCollectionBeta.exe (installer 2.7.7.15)
Code: Select all
// Call this API to hide expected object leaks.
// If more objects are leaked than expected, all will be shown.
function HideLeak (someClass: TClass; count: integer) : boolean; overload;
Re: RegisterExpectedMemoryLeak
Hi Mathias,
I have 4.0.9 installed but am getting some curious results with HideLeak. Could you please comment.
Here is the report from an IDE compile and run (D2007) of an application with no calls to HideLeak at the start of the DPR file.

The two leaks from TIdThreadSafeInteger, TIdCriticalSection are from Indy, and are unavoidable unless we want to mess with the sources. They are the ones I am wanting hide.
Here is the report with the following added:

and with the following...

So I can supress the TIdThreadSafeInteger but not the TIdCriticalSection.
Also, the other reported leaks of thread handles have call stacks that aren't in my application sources - might these be related to the Indy leaks?
I have 4.0.9 installed but am getting some curious results with HideLeak. Could you please comment.
Here is the report from an IDE compile and run (D2007) of an application with no calls to HideLeak at the start of the DPR file.

The two leaks from TIdThreadSafeInteger, TIdCriticalSection are from Indy, and are unavoidable unless we want to mess with the sources. They are the ones I am wanting hide.
Here is the report with the following added:
Code: Select all
MadExcept.HideLeak (TIdThreadSafeInteger, 1) ;
MadExcept.HideLeak (TIdCriticalSection, 1) ;

and with the following...
Code: Select all
MadExcept.HideLeak (TIdThreadSafeInteger, 1) ;
MadExcept.HideLeak (TIdCriticalSection, 2) ;

So I can supress the TIdThreadSafeInteger but not the TIdCriticalSection.
Also, the other reported leaks of thread handles have call stacks that aren't in my application sources - might these be related to the Indy leaks?
Re: RegisterExpectedMemoryLeak
Hmmmm... The leak checker handles TCriticalSection related objects differently. Is the problem fixed in the following build?rossmcm wrote:So I can supress the TIdThreadSafeInteger but not the TIdCriticalSection.
http://madshi.net/madCollectionBeta.exe (installer 2.7.8.1)
How should I know - without seeing the callstacks of those leaks? My telepathic powers only work on Sundays...rossmcm wrote:Also, the other reported leaks of thread handles have call stacks that aren't in my application sources - might these be related to the Indy leaks?
Re: RegisterExpectedMemoryLeak
Sorry Mathias, I thought it was Sunday when I wrote the post...How should I know - without seeing the callstacks of those leaks? My telepathic powers only work on Sundays...

I have installed the Dec 5 Beta and repeated the tests. With no calls to HideLeak:

With:
Code: Select all
MadExcept.HideLeak (TIdThreadSafeInteger, 1) ;
MadExcept.HideLeak (TIdCriticalSection, 1) ;



...so it looks as if you have successfully dealt with the TIdCriticalSection leak. Many thanks. As to the remaining leaks, the last one I think I have found. AfSafeSync is part of the AsyncFree serial COM port component:
Code: Select all
initialization
SyncMutex := CreateMutex(nil, False, nil); <------------------------------------------------- line 394
UniqueIDGenerator := 0;
finalization
ReleaseSyncHandler;
end.
Code: Select all
procedure ReleaseSyncHandler;
begin
if HandlerAllocated then
begin
HandlerAllocated := False;
DestroyWindow(SyncWnd);
FreeMem(SyncSlots);
end;
end;
Code: Select all
finalization
ReleaseSyncHandler;
CloseHandle (SyncMutex) ;
end.
P.S. I should mention that there is feature of MadExcept that has an advantage over FastMM's leak reporting: When FastMM generates the leak report, it does so by calling the routine from your application's program, whereas MadExcept seems to do it by spawning a separate viewer task. This means that the application EXE is released back to the IDE straight away and you can accumulate more than one viewer and leave them displayed while you recompile.
Re: RegisterExpectedMemoryLeak
The first one is not clear, the callstack is not giving us enough information. However, the middle one looks clear to me. It seems that msxmldom.TryObjectCreate in line 474 calls CoCreateInstance. That for some reason creates a thread and the thread handle is never freed. However, there isn't really anything you can do about this. So you'll have to simply ignore it.rossmcm wrote:The remaining two leaks I have no idea.
Both of the remaining leaks are true leaks (I think) but they should really not be shown by madExcept because they don't originate in your code. The leak checker is confused about that because madExcept hooks into thread creation (see "madExcept.HookedCreateThread" in the callstack) and that makes the leak checker believe that the leak is caused by Delphi code. Maybe I should look into fixing that, but it's not easy without being able to reproduce this. Do you have a way to reproduce one of these 2 remaining leaks in a simple test project? Maybe already calling CoCreateInstance is enough to reproduce one of the leaks?
The leak report itself is still created by the application EXE. However, the final report is then passed on to the viewer, which is a separate EXE. Yes, that is a nice advantage over FastMM's leak reporting. But it's not the only one. There are several more, let me list them, because I'm proud of my leak reporting solution:rossmcm wrote:P.S. I should mention that there is feature of MadExcept that has an advantage over FastMM's leak reporting: When FastMM generates the leak report, it does so by calling the routine from your application's program, whereas MadExcept seems to do it by spawning a separate viewer task. This means that the application EXE is released back to the IDE straight away and you can accumulate more than one viewer and leave them displayed while you recompile.
(1) The viewer GUI is of course much nicer than the simple FastMM reporting.
(2) You can double click callstack items in the viewer to make the Delphi editor jump to the right line.
(3) You can delete leaks you've fixed and save the remaining leaks to a file.
(4) Most importantly: FastMM4 only checks leaks in its own memory allocation routines. madExcept hooks about 400 win32 APIs to show you all kinds of other leaks FastMM4 has no idea of. E.g. check the "LeakTest" demo in the "Demos" folder and try which of those leaks FastMM4 detects.

Re: RegisterExpectedMemoryLeak
For what it is worth, Indy already registers those leaks, you do not need to do it manually. Indy has its own IdGlobal.IndyRegisterExpectedMemoryLeak() function that the affected units call at initialization. Internally, it calls Delphi's System.RegisterExpectedMemoryLeak() (D2006+) unless USE_FASTMM4 is defined, in which case it calls FastMM.RegisterExpectedMemoryLeak() directly. So as long as MadExcept is registering itself as Delphi's default memory manager and providing a callback for System.RegisterExpectedMemoryLeak() to call MadExcept.HideLeak() then Indy's leaks should already be getting registered automatically. I'm not against adding a new USE_MADEXCEPT define to Indy so it can call MadExcept.HideLeak() directly if needed, though.rossmcm wrote:For example, I know that Indy leaks a TIdThreadSafeInteger and 2 of TIdCriticalSection each time my app runs, but this is known about and inconsequential - so I have this at the start of my main program:Code: Select all
RegisterExpectedMemoryLeak (TIdThreadSafeInteger, 1) ; RegisterExpectedMemoryLeak (TIdCriticalSection, 2) ;
Re: RegisterExpectedMemoryLeak
madExcept's leak checking should automatically handle leaks registered via RegisterExpectedMemoryLeak() correctly. At least that's the theory...