Intel Inspector XE behavior in MFC

Intel Inspector XE behavior in MFC

An MFC application is reporting many memory leaks at exit using MFC's internal mem leak checker.

Running Inspector didn't reveal those leaks.

I've read that MFC can falsly report leaks because linked DLLs allocate memory before MFC's memory tracker becomes active.

I tried linking to MFC's DLLs first via linker options (confirmed by viewing the linker output in VERBOSE mode). MFC links first but the leaks are still showing.

The application is linked with several boost DLLs as well as 2-3 user DLLs which are not MFC DLLs.

Happens also when boost is linked statically.

Just opening and closing the application dumps many (tens) small leaked objects in the output window by MFC's memory leak tracker.

All the reported leaks are simple pointers (not MFC objects) and no reference to the originating source code.

I have a few questions:

1) Does MFC use a custom allocator (e.g. not malloc) and thus fools Inspector XE?

2) Can I somehow disable MFC's special memory allocator in debug builds?

3) Are the leaks reported falsely by MFC if Inspector XE says nothing's wrong?

Setup:

* Window 7 64 bit sp1

* VS2012 and VS2010

* Building 64 bit MFC application

* Boost 1.52 either dynamically or statically linked.

* Intel Parallel Studio XE 2013 update 1

If anyone has a suggestion, please share :)

Eric Gur, Intel QuickSync Decoder Author Processor Client Application Engineer Intel Corp.
18 posts / novo 0
Último post
Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.

>>...An MFC application is reporting many memory leaks at exit using MFC's internal mem leak checker...

Eric,

This is a really old story and, unfortunately, I see that another developer experienced it. I reported to Microsoft a memory leaks problem ( I called it as An Internal MFC Memory Leaks ) with MFC some time in 2006 and their response was:

'...this is a problem with your application...'

and I knew that my codes did Not Have Any memory leaks. Their response "ignited" my interest in implementation of my own absolutely portable and as simple as possible Memory Leaks Detection software subsystem ( implemented in 2007 and currently used on another project ).

So, I'll follow up on your post later with more details. Would you be able to provide a small test case without Boost library and with 32-bit configuration ( without 64-bit configuration )?

For years I didn't have any issues with MFC's memory leaks detector, it was very useful, only lately I came across this issue in a mature application.

I can't build the app in 32 bit or without boost.

I'll try to introduce various memory leaks within different modules of the application and see if they are caught by wither MFC or Inspector.

But before doing reverse engineering, maybe someone has some insight on the matter and maybe a workaround.

Eric Gur, Intel QuickSync Decoder Author Processor Client Application Engineer Intel Corp.

Inspector XE Update 4 contains some fixes for handling MFC's debug 'new'.   The problem shows up as false reports of mismatched allocation/deallocation - IXE would miss the debug 'new', but catch the underlying malloc.   It would subsequently see the 'delete', and report a problem.

Unfortunately, I don't think this fix will address the issue you're seeing, but it still may be worth trying the latest IXE update.

>>...For years I didn't have any issues with MFC's memory leaks detector, it was very useful, only lately I came across this issue
>>in a mature application...

More technical details? A piece of code?

>>...But before doing reverse engineering...

MFC is provided with sources and step into the code always helps to understand what is going on. Microsoft doesn't hide anything in the library and, to some degree, it could be considered as Open Source.

>>...maybe someone has some insight on the matter and maybe a workaround.

Could you post the Memory Leaks report from the Output Window of your Visual Studio? Your current description is too generic, however, I can list three possible problems:

- A memory allocation / deallocation problem in your C/C++ application ( memory leaks )
- A memory allocation / deallocation problem in Boost library ( memory leaks )
- A memory allocation / deallocation problem in MFC library ( memory leaks )

and please consider All of them during investigation.

Q: Does MFC use a custom allocator (e.g. not malloc) and thus fools Inspector XE?

No and It doesn't "fool" Inspector XE. The core of memory leaks detection API for MFC is very old and possibly was implemented some time between 1992 and 1994 ( in Visual C++ v1.5 / v2.0 ) when, as far as I know, Inspector XE did Not exist. There is No Any reason to "fool" Any software.

Q: Can I somehow disable MFC's special memory allocator in debug builds?

Please explain me how is it going to fix memory leaks? Or, you're simply interested to verify what Inspector XE will report?

1. As soon as CRTDBG_MAP_ALLOC is defined then malloc is mapped to malloc_dbg. Take into account that there is a set of CRT-functions for allocation / deallocation of alligned memory ( it is documented in MSDN ).

2. A call to _CrtSetDbgFlag( 0 ) disables reporting.

Q: Are the leaks reported falsely by MFC if Inspector XE says nothing's wrong?

No. If MFC detects a memory leaks and Inspector XE doesn't then there is a problem / issue with memory leaks detection in Inspector XE.

>>... Are the leaks reported falsely by MFC...

I'd like to make a special post regarding a term False Memory Leaks widelly used by some software engineers:

If MFC memory leaks detection API ( based on _Crt<...> functions ) Reports a memory leaks it is Not a False one, and it is a Real one.

>> More technical details? A piece of code?

The code is an internal tool and I can't publically send pieces of it. When there were leaks in the executable (vs the DLLs) MFC reported them - it included a source name+line number in the report.

>> No and It doesn't "fool" Inspector XE.

It's possible to "fool" memory checkers by replacing malloc/new/new[] with different functions. When I used TBB malloc (highly recommended!) in Linux, various tools stopped reporting leaks. The replacement malloc or memory manager can call VirtualAlloc for large blocks and free everything at exit so no leaks will be detected. This behavior is normal for memory managers.

>>  As soon as CRTDBG_MAP_ALLOC is defined then malloc is mapped to malloc_dbg. Take into account that there is a set of CRT-functions for allocation / deallocation of alligned memory ( it is documented in MSDN ).

If I remember correctly, malloc_dbg is identified by Inspector, so that would not help. I would cause problems (crash) when memory is freed across DLL borders.

>> I'd like to make a special post regarding a term False Memory Leaks widelly used by some software engineers:

If MFC memory leaks detection API ( based on _Crt<...> functions ) Reports a memory leaks it is Not a False one, and it is a Real one.

I've read reports that if globals are instantiated (and malloc) before MFC is loaded that can happen. I tried linking to MFC first so I believe the leaks are real.

As for the source of the leak, it indeed could be anywhere. Boost is my usual suspect. I'll post a dump from VS when I get back to work. Basically simple blocks ranging from 8-100 bytes.  About 50 of them. Their contents look like pointers (4 non zero bytes followed by 4 zero bytes) - this is 64 bit builds.

Eric Gur, Intel QuickSync Decoder Author Processor Client Application Engineer Intel Corp.

>>...The code is an internal tool and I can't publically send pieces of it. When there were leaks in the executable
>>(vs the DLLs) MFC reported them - it included a source name+line number in the report.

It is not clear for me how anybody could help you if no technical details provided.

>>...It's possible to "fool" memory checkers by replacing malloc/new/new[] with different functions...

MFC doesn't do it with '...different functions...'. We're not speaking about anything else, right?

>>...If I remember correctly, malloc_dbg is identified by Inspector...

This is incorrect and you need to look at malloc.h and crtdbg.h header files. Or you can see it when debugging ( simply step into the code when malloc/new is called ).

>>...I've read reports that if globals are instantiated (and malloc) before MFC is loaded that can happen...

Web-link(s) for these reports, please. I'd like to review these reports and at the moment I consider your statement as some kind of "speculation". In order to verify if some DLL(s) is/are loaded before MFC DLLs do the following:

- Start your application in Debugger
- Don't do anything
- Exit your application
- Review order of loaded DLLs in Visual Studio's Output WIndow ( find all references for MFC, Boost, etc DLLs )
- Review order of unloaded DLLs in Visual Studio's Output WIndow
- And one more, Is there a memory leaks dump?

>>...I reported to Microsoft a memory leaks problem ( I called it as An Internal MFC Memory Leaks ) with MFC
>>some time in 2006...

I found the report in my records:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DevNote #0004 - An Internal MFC Memory Leaks

If a call to _CrtDumpMemoryLeaks() is done it detects some Memory Leaks for an MFC-based application:

[ Codes deleted ]

A Visual Studio's Output Window looks like:
...
Detected memory leaks!
Dumping objects ->
...\atlmfc\src\mfc\dllmodul.cpp(133) : {84} client block at 0x0036B7B0, subtype c0, 64 bytes.
a CDynLinkLibrary object at $0036B7B0, 64 bytes
{79} client block at 0x0036B5A0, subtype c0, 64 bytes.
a CDynLinkLibrary object at $0036B5A0, 64 bytes
{69} client block at 0x00367190, subtype c0, 64 bytes.
a CDynLinkLibrary object at $00367190, 64 bytes
Object dump complete.
...
This is by design of the MFC! The MFC creates several objects of CDynLinkLibrary
type when processing DLL_PROCESS_ATTACH event in InternalDllMain() function,
and deletes these objects of CDynLinkLibrary type when processing
DLL_PROCESS_DETACH event. That is, just before unloading the DLL from memory.

Since DLL_PROCESS_DETACH event is processed later a call to _CrtDumpMemoryLeaks()
detects that some objects are still NOT deleted. Remember, that all objects of
CDynLinkLibrary type are MFC-Internal objects. But, if references to some
another objects appear in the Output Window it means that the Application has
Memory Leaks.

Here's a sample of the dump, it's quite long but the rest don't reveal any more information:

[code]

Detected memory leaks!
Dumping objects ->
{7662} normal block at 0x0000000002760B80, 64 bytes long.
Data: <`qt rt > 60 71 74 02 00 00 00 00 00 72 74 02 00 00 00 00
{7371} normal block at 0x0000000002752BB0, 8 bytes long.
Data: <@ v > 40 AA 76 02 00 00 00 00
{7259} normal block at 0x0000000002766CB0, 24 bytes long.
Data: <P. > 50 2E F0 F2 FE 07 00 00 01 00 00 00 01 00 00 00
{7257} normal block at 0x0000000002766900, 16 bytes long.
Data: <8 & > 38 D1 26 00 00 00 00 00 00 00 00 00 00 00 00 00
{7256} normal block at 0x0000000002766850, 64 bytes long.
Data: <Phv Phv > 50 68 76 02 00 00 00 00 50 68 76 02 00 00 00 00
{7255} normal block at 0x000000000274AC20, 16 bytes long.
Data: < & > 08 D1 26 00 00 00 00 00 00 00 00 00 00 00 00 00
{7254} normal block at 0x000000000274ABB0, 8 bytes long.
Data: < & > E0 D0 26 00 00 00 00 00
{7253} normal block at 0x000000000274AB30, 24 bytes long.
Data: < % > A8 25 F0 F2 FE 07 00 00 02 00 00 00 02 00 00 00
{7252} normal block at 0x000000000274AA90, 48 bytes long.
Data: < t 0 t > 90 AA 74 02 00 00 00 00 30 AB 74 02 00 00 00 00
{7251} normal block at 0x000000000274AA10, 24 bytes long.
Data: <P. > 50 2E F0 F2 FE 07 00 00 01 00 00 00 01 00 00 00

[/code]

This scenraio is just opening and closing the app.

MFC DLL (mfc100d.dll) is loaded around the middle of load list.

A few links for false MFC leaks:

http://stackoverflow.com/questions/628021/false-memory-leaks-in-a-mfc-pr...

http://binglongx.wordpress.com/2009/05/28/false-memory-leaks-detected-in...

Sergey, you're right that I'm speculating. At this stage I'm asking questions :)

Eric Gur, Intel QuickSync Decoder Author Processor Client Application Engineer Intel Corp.

>>A few links for false MFC leaks:
>>
>>http://stackoverflow.com/questions/628021/false-memory-leaks-in-a-mfc-pr...
>>
>>http://binglongx.wordpress.com/2009/05/28/false-memory-leaks-detected-in...

I'll take a look and respond regarding a concept 'False Memory Leaks'.

>>...This scenraio is just opening and closing the app.
>>
>>MFC DLL (mfc100d.dll) is loaded around the middle of load list.

Could you post to the thread or e-mail me ( using Private Messaging system ) that list?

As soon as you're back to work:

1. In your Visual Studio create a new MFC project and it should match to what you have, Dialog-based ( DLG ), SDI-based, or MDI-based test application
2. Build the test application
3. Start the test application in Debugger
4. Don't do anything
5. Exit the test application
6. Is there a memory leaks dump?
7. Add that code in OnInitDialog ( for DLG ) or in InitInstance ( for SDI & MDI ):
...
#define _SIMULATE_MEMORYLEAKS // Use that macro to control simulation of memory leaks / #undef when you don't need it
...
#ifdef _SIMULATE_MEMORYLEAKS
char *pchBuffer = NULL;
pchBuffer = new char[ sizeof( char ) * 777 ];
#endif
...
8. Repeat steps 2 to 6
9. Add Boost headers and libraries ( Don't add any functionality yet )
10. Repeat steps 2 to 6
11. Add some MFC functionality that is used in your production application ( It could be a difficult process )
12. Repeat steps 2 to 6
13. Add some Boost functionality that is used in your production application ( It could be a difficult process )
14. Repeat steps 2 to 6

and so on.

The main idea is as follows: you need to use a very clean test application in order to reproduce the same memory leaks. If you manage to use a similar approach in your production application it will also work and in that case you will need to start commenting out some pieces of codes. It means, as soon as memory leaks are Nor detected a last commented piece of codes is the root cause of these memory leaks.

You have ~50 memory leaks and I'd like to share my experience: in 2007 in some 3-D imaging application ( MFC & QT & Internal libraries ) due to some problems we had to deal with more than 30,000 memory leaks.

A couple of project organization advises. A very strict approach in the development process is as follows:

- A developer is Not allowed to check in codes if codes are Not pass a review by another software developer
- A developer is Not allowed to check in codes if codes are Not checked for memory leaks
- Every (!) class, function, macro, etc must have an independent test case ( For example, for a middle size project I have more than 45,000 code lines of different tests )

I believe that in two cases ( web-links you've provided ) developers detected some memory leaks. However, in the 1st case a developer uses a third part DLL and in both cases memory leaks dump are Not provided. Another thing is ( from the 1st web-link ):

...Those leaks are legitimate...

My question is what are legitimate leaks?

PS: Sorry for a completely different example. Let's imaging,,, A Person calls to a City of Abc to report a problem and here is a conversation with an Operator:

Caller: Hi, I have a water leak in my basement!
Operator: How bad is it?
Caller: It is around 10-15cm of water...
Operator: Don't worry, it is a legitimate water leak...
or
Operator: Don't worry, it is a false water leak...

What would you tell to Operator?

Sergey, I followed your comments as well as looked at the (few) resource and memory leaks leask  reported by Inspector and found that the main problm was with boost::threadpool. The application seems to create and destroy the threadpool multiple times during the life cycle of the application. When turning the threadpool to a global, the memory leaks are greatly reduced.

Thanks a lot for your time and effort!

Eric Gur, Intel QuickSync Decoder Author Processor Client Application Engineer Intel Corp.

Thanks for the update, Eric.

I also would like to mention that all cases when container classes are used, MFC, or STL, or Boost, need to be verified as well. Unfortunately, all these verifications are time consuming when application is mature and has hundred of thousands code lines.

Please keep everybody informed.

Well, I wasn't asking anyone to help me het rid of the leaks, just wanted to know how things work with MFC + Inspector.

I want to thank Sergey for his effort and time. I got my all my answers.

Also, thanks Mark for pointing me to the new version.

Eric Gur, Intel QuickSync Decoder Author Processor Client Application Engineer Intel Corp.

May it's not relevant here, but I don't know where to post an IntelQuickSyncDecoder.dll small memory leaking problem.

We are using IntelQuickSyncDecoder.dll decording video content by LAVfilter https://code.google.com/p/lavfilters/. there is always a small mount of memory leaking in QuickSyncDecoder.  

By Dr.memory tools there are memory leaking report:

Error #1: LEAK 24 direct bytes 0x02f8f530-0x02f8f548 + 536 indirect bytes
# 0 replace_RtlAllocateHeap               [d:\drmemory_package\common\alloc_replace.c:3432]
# 1 libmfxhw32.dll!MFXVideoVPP_GetVPPStat+0x30b124 (0x059eb435 <libmfxhw32.dll+0x32b435>)
# 2 libmfxhw32.dll!MFXVideoVPP_GetVPPStat+0x30b33e (0x059eb64f <libmfxhw32.dll+0x32b64f>)
# 3 libmfxhw32.dll!MFXVideoVPP_GetVPPStat+0x10528b (0x057e559c <libmfxhw32.dll+0x12559c>)
# 4 libmfxhw32.dll!MFXVideoVPP_GetVPPStat+0x10a397 (0x057ea6a8 <libmfxhw32.dll+0x12a6a8>)
# 5 libmfxhw32.dll!MFXVideoVPP_GetVPPStat+0x10507c (0x057e538d <libmfxhw32.dll+0x12538d>)
# 6 libmfxhw32.dll!MFXVideoVPP_GetVPPStat+0x62b53  (0x05742e64 <libmfxhw32.dll+0x82e64>)
# 7 libmfxhw32.dll!MFXVideoDECODE_Init   +0x155    (0x056da226 <libmfxhw32.dll+0x1a226>)
# 8 IntelQuickSyncDecoder.dll!getVersion +0x1093   (0x502a7e34 <IntelQuickSyncDecoder.dll+0x7e34>)
# 9 IntelQuickSyncDecoder.dll!getVersion +0x51f2   (0x502abf93 <IntelQuickSyncDecoder.dll+0xbf93>)
#10 zVideoDecoderd.dll!CDecBase::Decode   [c:\third_party\lav\lavfilters.62.0 - playground\decoder\lavvideo\decoders\decbase.h:97]

There is no getVersion call in the client code, my guess is  there is a getVersion call IntelQuickSyncDecoder.dll but not free that memory.

 

Faça login para deixar um comentário.