Solved

Dialogbox API leak?

Posted on 2016-10-15
18
59 Views
Last Modified: 2016-10-22
Hi dear Experts:

I got memory leak error from Microsoft Visual studio 2015 diagnostic tools,

I am calling function:

DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), NULL, About, 0);

For each  time I call this API, I got leak if I set break point just before after this call, the diagnostic tools window shows the memory keep increasing.

I just wonder if this is a real leak or just a false alarm from the tool?

I found that if I set the parent window handle to be not a null, then there is no leak at this time.

I have attached the picture.

And I also attached the source code zip file.

Thanks for any help.
DialogboxAPILeak.png
TestWin32Dialog.cpp
TestWin32Dialog.h
TestWin32Dialog.rc
Resource.h
0
Comment
Question by:Evan Li
  • 10
  • 5
  • 3
18 Comments
 
LVL 32

Expert Comment

by:sarabande
ID: 41845621
you should know that DialogBox is a c function provided by c winapi. because of that DialogBox cannot handle it owns memory management by means of destructors but requires the caller to provide enough (tempory) memory for to working properly. a leak detected in DialogBox always is in the responsibility of the calling function which didn't free all the buffers allocated after DialogBox has finished.

Sara
0
 

Author Comment

by:Evan Li
ID: 41845752
This is the first time that I hear that I need to free the buffer for dialogbox API, I did not allocate memory for this API, I do not have an handle or pointer to free the buffer, it is all handled by Windows. Please tell me further, if there is any way we can do it? Thanks.
0
 

Author Comment

by:Evan Li
ID: 41847367
Hi Sara, here are your answer in the over question thread:

but there is no resource load or memory allocation here

 and what is about:

1:wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));



Select all
 
Open in new window

 where did you free this resource?

 can you show a picture of the dialog or post the rc file?

 note, a visual c++ program uses a framework via stdafx.h. even if you use c code for dialog processing you still catch some automatic instantiations from framework. in the debugger things go worse since the debugger needs to make extra allocations for each variable you used. so if you detect leaks while running the program in debug mode but can't detect leaks in release mode, all your efforts are wasted.

 Sara
0
 

Author Comment

by:Evan Li
ID: 41847375
I have attached the rc files and cpp files here,

Most code is generated from VS wizard, what I have changed is the about dialog box. Just open and close the about dialogbox, is not leak, if I changed the parent window to be null, then it is leaking.

Just use VS diagnostic tools for DialogboxParam, one statement.
The statement you said:

wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

Is not in any about box call back function. So it does not matter. If this leak, it does it for the whole program, it will not contribute to dialogbox leak.
0
 

Author Comment

by:Evan Li
ID: 41847382
OK, I have attached the picture of the program. It is a App Wizard generated program, I just changed the window handle for dialog box, and used VS diagnostic tool for only one statement, it gets consistent leak.
MemoryLeakTest.png
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 41847765
Hi Evan Li,

IMO you should try to find out if there's probably just a problem in the displayed diagnostic info. To verify the memory leaks you can try dumping them using _CrtMemCheckpoint and _CrtMemDumpAllObjectsSince, i.e. somhow like this:
bool CallDialog(HWND hWnd)
{
	_CrtMemState state = {};
	_CrtMemCheckpoint(&state);

	INT_PTR nResponse = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), NULL, About, 0);

	_CrtMemDumpAllObjectsSince(&state);
	return true;
}

Open in new window

In a DEBUG build this should ouput a list of all memory leaks produced by DialogBoxParam.

ZOPPO
0
 
LVL 32

Expert Comment

by:sarabande
ID: 41847787
you may try to create an mfc app dialog-based. you may use the app wizeard to copy the dialog resource from your current project to the mfc project. i wonder what the leak diagnostic would tell with this approach.

Sara
0
 

Author Comment

by:Evan Li
ID: 41849499
Hi, Zoppo:

I used Visual leak detector and CRT memory check APIs. both does not show memory leaks,

I did my test again, Here is what I have got:

Dumping objects ->
Object dump complete.
Dumping objects ->
Object dump complete.
Dumping objects ->
Object dump complete.
Dumping objects ->
Object dump complete.

But in diagnostic tools, it indicated that the memory keep getting up.
0
 

Author Comment

by:Evan Li
ID: 41849514
MFC code:

      CAboutDlg aboutDlg;
      aboutDlg.DoModal();

does not have a leak from diagnostic tools.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 32

Expert Comment

by:sarabande
ID: 41849542
as told when creating the window you were loading some resources which in my opinion were not freed by your code.

about dialog only should be tested after you opened it at least once (in your menu). mfc Dialogs load their resources in OnInitDialog which was virtually called as a response to WM_INIT_DIALOG message. since you have the mfc code you could debug what happens when a dialog was created and when it finally was destroyed. note, the creation and the destroying is a two-step action.  the final freeing happens in OnDestroy and OnNcDestroy.

Sara
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 41849635
ok, that's really strange, I can reproduce it too now.

@Sara: to reproduce it you can simply create a Win32 (none-MFC) app from the scratch, it looks very similar to the code attached above. When debugging this app no memory leaks are shown when taking snapshots before and after showing the About-dialog.

BUT: As soon as you use NULL instead of hwnd in the call to DialogBox in WndProc the behavior changes and the diagnostic tool shows memory leaks between snapshots taken before and after showing the About-dialog:
snapshots taken after showing and closing the About-dialogHere's a bit more info about the leak between the last two snapshots:
memory leak infoI have no idea why passing NULL as parent window leads to this problem, but I fear there's not a lot you can do against because it happens quite deep within Windows API calls (I attached a screenshot of the call-stack because unfortunateley the diagnostic tool's view doesn't have a function to copy/export the stack as text).

@Evan Li: IMO you only have two possibilities:

1. Change the code to use hwnd instead of NULL again. (BTW: why do you want to use NULL here at all?)
2. Live with the memory leak. It's only 24 bytes each time the dialog is opened, so it's extremely unlikely this will ever lead to a problem.

Best regards,

ZOPPO
memleakstack.png
1
 

Author Comment

by:Evan Li
ID: 41850795
Thank you Zoppo,

Here is my Question,
1>I have MS Diagnostic tool, which can report me the memory leak
2>I have Visual Leak Detector
3>I have CRT checkMemory APIs just as you suggested.

they do not produce the consistent result. Which tool I should trust?

Here you saw the situation that Visual Studio Diagnostic tools reported error, but CRT memory check API says no memory leak, I have situation that Diagnostic tool told me there is not leak but CRT memory check shows errors.

Which one to trust, In both situation, I could not find the root cause.

Thank you for your help again.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 41851563
can we call 24 bytes not freed a leak? i would say only if the next calls again would allocate the same amount. you should see that a static instantiation of a 24 byte structure - for example to serve as a pseudo parent window - might be responsible for the growing.

Sara
0
 
LVL 30

Accepted Solution

by:
Zoppo earned 500 total points
ID: 41851676
ok, I did some more analyzing and think it is a real memory leak. I wrote a function to dump out some statistics about current allocation on the heap:
static void DumpHeapStatistics()
{
	_HEAPINFO hinfo = {};
	int nStatus;
	size_t nSize = 0;
	size_t nCount = 0;

	while ( ( nStatus = _heapwalk( &hinfo ) ) == _HEAPOK )
	{
		bool bUsed = ( hinfo._useflag == _USEDENTRY );
		if ( bUsed )
		{
			nSize += hinfo._size;
			nCount++;
		}
	}

	TRACE( "*** Heap size: %Ii, block count: %Ii ***\n", nSize, nCount );
}

Open in new window

Then I changed the code where I open the dialog to this:
    case IDM_ABOUT:
	{
		_CrtMemState state = {};
		_CrtMemCheckpoint( &state );

		DumpHeapStatistics();

		DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), NULL, About);

		DumpHeapStatistics();

		_CrtMemDumpAllObjectsSince( &state );
	}

Open in new window

Then I started the application and opened and closed the dialog several times - here's the output:
d:\projects\test\testleak.cpp(133) : *** Heap size: 143220, block count: 798 ***
d:\projects\test\testleak.cpp(133) : *** Heap size: 144620, block count: 804 ***
Dumping objects ->
Object dump complete.
d:\projects\test\testleak.cpp(133) : *** Heap size: 144132, block count: 804 ***
d:\projects\test\testleak.cpp(133) : *** Heap size: 144156, block count: 805 ***
Dumping objects ->
Object dump complete.
d:\projects\test\testleak.cpp(133) : *** Heap size: 144156, block count: 805 ***
d:\projects\test\testleak.cpp(133) : *** Heap size: 144668, block count: 806 ***
Dumping objects ->
Object dump complete.
d:\projects\test\testleak.cpp(133) : *** Heap size: 144180, block count: 806 ***
d:\projects\test\testleak.cpp(133) : *** Heap size: 144204, block count: 807 ***
Dumping objects ->
Object dump complete.
d:\projects\test\testleak.cpp(133) : *** Heap size: 144204, block count: 807 ***
d:\projects\test\testleak.cpp(133) : *** Heap size: 144228, block count: 808 ***
Dumping objects ->
Object dump complete.
d:\projects\test\testleak.cpp(133) : *** Heap size: 144228, block count: 808 ***
d:\projects\test\testleak.cpp(133) : *** Heap size: 144252, block count: 809 ***
Dumping objects ->
Object dump complete.
d:\projects\test\testleak.cpp(133) : *** Heap size: 144252, block count: 809 ***
d:\projects\test\testleak.cpp(133) : *** Heap size: 144276, block count: 810 ***
Dumping objects ->
Object dump complete.
d:\projects\test\testleak.cpp(133) : *** Heap size: 144276, block count: 810 ***
d:\projects\test\testleak.cpp(133) : *** Heap size: 144300, block count: 811 ***
Dumping objects ->
Object dump complete.

Open in new window

It seems the first time the dialog is called more 'leaks' are produced (6 blocks, 1400 bytes), each following call adds one 24 bytes block.

I have no idea why the _CrtDump... functions don't report this, but IMO there really is a memory leak, anyway with just 24 bytes for each time a dialog is opened I think it can be ignored.

ZOPPO
1
 

Author Closing Comment

by:Evan Li
ID: 41853261
Thank you both Zoppo and Sara.

This should be an API bug. But we need to work around it.

Thank you again.
0
 

Author Comment

by:Evan Li
ID: 41854741
Hi Zoppo,
I have a question in another thread that is related to this one.  From time to time, I got leak, says "unresolved allocation" in Visual studio, I could not find where my code is wrong if you look at call stack. How are you going to do this in this situation?
0
 

Author Comment

by:Evan Li
ID: 41854743
0
 
LVL 32

Expert Comment

by:sarabande
ID: 41855191
yes, you should close it as the last comment pointed to this thread.

Sara
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now