?
Solved

How do you detect resource leaks in an MFC MDI application?

Posted on 2005-05-13
26
Medium Priority
?
420 Views
Last Modified: 2013-11-20
Hi everyone.  I have an MDI application which has a drag/drop interface.  The problem that I'm having is that when I start dragging objects around on my View, memory starts growing very quickly.  The program doesn't have any detectable memory leaks that are obvious to me (ie.  all 'operator new's' are matched up with operator 'delete') and the program doesn't report any memory leaks when I exit the program.  I am suspecting that I am leaking other resources, such as GDI objects, fonts, brushes, etc...  Does anybody have any good ideas about how I can go about detecting resource leaks?  The program is fairly large, so it's hard to isolate the exact moment where it starts growing.

Let me know if there is other information that I can give you that may be helpful.  Thanks.
0
Comment
Question by:mromeo
  • 12
  • 7
  • 5
  • +1
25 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 13996139
>Does anybody have any good ideas about how I can go about detecting resource leaks?  
Yes, best option is to read carefully your code, I think

in every function that works with drag and drop, you must ensure to deselect every resource type like: bitmaps, pens, brushes, fonts, etc.
So, every first time you select and object in a function (with SelectObject, saving previous object) you have to unselect it using SelectObject again.
 
0
 
LVL 30

Expert Comment

by:Axter
ID: 13996234
Are you calling _CrtCheckMemory in your application destructor?
0
 

Author Comment

by:mromeo
ID: 13996316
Yes, I'm calling it in ExitInstance.  It doesn't give me any output to the output window.  Is there sometng I else I need to call to use it?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:mromeo
ID: 13996497
I added a few checkpoints and then call __CrtMemDifference/_CrtDumpMemStatistics, but I get no output.   What should I see in the debug window?
0
 
LVL 30

Expert Comment

by:Axter
ID: 13996565
>>Is there sometng I else I need to call to use it?

No, that should do it.

>> What should I see in the debug window?

You should get a message saying memory leak detected, and it should include a file name and line count.

You can force it to give you a leak by adding the following in your ExitInnstance function:
int *dummy = new[12345];

And don't delete it.
Then you'll see what the leak meassage should look like.
0
 
LVL 30

Expert Comment

by:Axter
ID: 13996570
Exactly what makes you think you'r getting a leak?
0
 

Author Comment

by:mromeo
ID: 13996597
Well, it's possible that it's not a leak, but something is making memory grow very quickly in my application.  When I start dragging objects in my main View, memory starts growing by about 100k every 5 seconds.  That's before I even do the Drop.  It happens during OnDragOver.  I have been going over this code so carefully, and I can't figure out what's doing it.  I'm trying to figure out if its a system resource or something.  I don't know where to look next.
0
 

Author Comment

by:mromeo
ID: 13996622
I put an intentional leak right before I call _CrtDumpMemoryLeaks and it didn't tell me that I leaked anything.  Something isn't right.

      char *a = new char[123456];

      int ret = _CrtCheckMemory();
       _CrtDumpMemoryLeaks( );

0
 
LVL 30

Expert Comment

by:Axter
ID: 13996747
Remove all other _Crt??? function calls, and only make the _CrtDumpMemoryLeaks() after the created memory leak.

You should also comment out any other _Crt??? code in your entire app.
One of them could be causing the problem.

You should just do the _CrtDumpMemoryLeaks() call by itself.
0
 
LVL 30

Expert Comment

by:Axter
ID: 13996762
Also add a TRACE before calling _CrtCheckMemory.
char *a = new char[123456];
TRACE("****** Here comes memory leak dump ********");
_CrtDumpMemoryLeaks( );
0
 

Author Comment

by:mromeo
ID: 13997364
Ok, well, I got rid of the couple of minor leaks that I had.  Nothing has really changed.  When I start dragging objects around (which are CStatic objects), memory starts growing very rapidly.  As soon as I release the mouse and OnDrop is called.  It stops growing.  Where would you start looking?  I've been over and over this code.
0
 

Author Comment

by:mromeo
ID: 13997697
Ok, well, it appears to be totally unrelated to Dragging.  If I simply start resizing the main window (which has NO MDI windows open), memory start to grow.  I don't really know what to make of this.  Has anybody ever seen the app grow just by resizing the main FrameWnd?
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 13997736
Post your OnSize() event.
0
 

Author Comment

by:mromeo
ID: 13998257
I don't have one.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 13998319
then it is your paint function, every time you drag the mouse to resize, a paint is made.
You can try:

CYourView::OnPaint()    // I suposse you have implemented this function, or could be OnPaint
{
     ::MessageBeep(MB_OK);

     // All your code here
}
0
 

Author Comment

by:mromeo
ID: 13998356
No, no, no.  I don't even have a view window open.  All I have is the MainFrame.  No views, no documents, etc have even been created.  All I'm doing is dragging the lower right corner to resize the window and the memory just grow and grow and grow.  I have no OnSize method and only one OnPaint method which is not being called.  I'm using Spy++ to try to figure out what other messages are being sent.  I tried a smaller test mdi application, and it does not happen with that program.

0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 13998429
>>  I am suspecting that I am leaking other resources, such as GDI objects, fonts, brushes, etc...  Does anybody have any
>> good ideas about how I can go about detecting resource leaks?

Hmm, since you mentioned GDI objects, I supossed you had a painting function.
Then, if you say you have not child windows (doc/view), could you post your entire CMDIFrameWnd implementation?
0
 

Author Comment

by:mromeo
ID: 13998492
Right, that's what I thought it was until I realized it was happening even without the View window open.  

Here's the code.  Don't know how much it will help out of context:


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
      //{{AFX_MSG_MAP(CMainFrame)
      ON_WM_CREATE()
      ON_COMMAND(ID_FILE_CHOOSE_URL, OnFileChooseUrl)
      ON_COMMAND(ID_WINDOW_TILE_VERT, OnWindowTileVert)
      ON_WM_CLOSE()
      ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
      ON_COMMAND(ID_FILE_SAVEALL, OnFileSaveall)
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

static UINT indicators[] =
{
      ID_SEPARATOR,           // status line indicator
      ID_INDICATOR_DATABASE,
      ID_INDICATOR_POS,
      ID_INDICATOR_CAPS,
      ID_INDICATOR_NUM,
      ID_INDICATOR_SCRL,
};
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
}

CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
      if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
      
      if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
            | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
            !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
      {
            TRACE0("Failed to create toolbar\n");
            return -1;      // fail to create
      }

      if (!m_wndStatusBar.Create(this) ||
            !m_wndStatusBar.SetIndicators(indicators,
              sizeof(indicators)/sizeof(UINT)))
      {
            TRACE0("Failed to create status bar\n");
            return -1;      // fail to create
      }

      // create the main toolbar.
      m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
      CString toolbarTitle;
      toolbarTitle.LoadString(IDR_MAINFRAME);
      m_wndToolBar.SetWindowText (toolbarTitle);

      EnableDocking(CBRS_ALIGN_ANY);
      DockControlBar(&m_wndToolBar);

      // set the window placment.
      WINDOWPLACEMENT wp;
      if (ReadWindowPlacement(&wp))
            SetWindowPlacement(&wp);

      return 0;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
      if( !CMDIFrameWnd::PreCreateWindow(cs) )
            return FALSE;
      
      return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
      CMDIFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
      CMDIFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers

void CMainFrame::OnFileChooseUrl()
{
      // display the URL dialog box.
      CURLDialog      urlDlg;
      if (urlDlg.DoModal() == IDOK)
      {
      }
}

void CMainFrame::OnWindowTileVert()
{
      MDITile(MDITILE_VERTICAL);      
}

void CMainFrame::OnClose()
{
      WINDOWPLACEMENT    wp;

    // before it is destroyed, save the position of the window
    wp.length = sizeof wp;

    if ( GetWindowPlacement(&wp) )
    {
        if ( IsIconic() )
          // never restore to Iconic state
          wp.showCmd = SW_SHOW ;

        if ((wp.flags & WPF_RESTORETOMAXIMIZED) != 0)
          // if maximized and maybe iconic restore maximized state
          wp.showCmd = SW_SHOWMAXIMIZED ;

        // and write it to the .INI file
        WriteWindowPlacement(&wp);
    }
          
      CMDIFrameWnd::OnClose();
}

BOOL CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT *pwp)
{
      return CAppPreferences::SaveWindowPosition(pwp, STR_MAINWIN_POS);
}

BOOL CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT *pwp)
{
      return CAppPreferences::GetWindowPosition(pwp, STR_MAINWIN_POS);      
}


void CMainFrame::SetStatusBar(int pane, CString &text)
{
      m_wndStatusBar.SetPaneText(pane, text);
}


void CMainFrame::OnFileClose()
{
      // check to see how many documents are open.
      // when there are none left, change the status bar
      // to read the current url db value.

      CDocument *doc = GetActiveDocument();
      if (doc == NULL)
      {
            CString prefsURL = CAppPreferences::Fetch_GetModulesURL();
            SetStatusBar(1, prefsURL);
      }
}

void CMainFrame::OnFileSaveall()
{
      MessageBox("Save All Not Yet Implemented");

      // need to get all documents and tell each one to save
      CScreenMaintenanceApp *theApp = static_cast<CScreenMaintenanceApp *>(AfxGetApp());
      
      theApp->SaveAllModified();

}
0
 

Author Comment

by:mromeo
ID: 13998559
It appears to be related to the toolbar.  When I comment out the code to create the toolbar, the problem goes away.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 13998579
Don't what are these functions (maybe this: http://www.codeproject.com/dialog/windowpres.asp) but you can try to remove them temporarily:

BOOL CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT *pwp)
{
     return CAppPreferences::SaveWindowPosition(pwp, STR_MAINWIN_POS);
}

BOOL CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT *pwp)
{
     return CAppPreferences::GetWindowPosition(pwp, STR_MAINWIN_POS);    
}
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 13998604
>>It appears to be related to the toolbar.  When I comment out the code to create the toolbar, the problem goes away.
If your toolbar is a custom toolbar, it could be.
0
 

Author Comment

by:mromeo
ID: 13998620
What do you mean by "custom" toolbar?  I haven't done anything special to it.  I have a member variable called m_wndToolBar.  All the code that deals with it is in the code I posted.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 13998713
What do you mean by "custom" toolbar?
I mean some derived toolbar that you can obtain in the internet, some of these objects have memory leaks.
But if you say it is a standard CToolbar object, then it is strange that it produces a memory leak.
You toolbar buttons must be related to some application functions, am I correct?
If so, maybe you have some 'OnUpdateSomeCommand()' functions to manage buttons state, there could be a possible point of leakage.
0
 

Author Comment

by:mromeo
ID: 13998982
It's not that either.  All my ::OnUpdateXXX methods are in the view or document classes.  I guess I'm goint to ave to rip this code apart, line by line to figure out what is going on.  Maybe I need to re-assemble the toolbar to see at what point this memory problem starts.
0
 
LVL 3

Accepted Solution

by:
NawalKishore1976 earned 2000 total points
ID: 14008713
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses
Course of the Month16 days, 14 hours left to enroll

862 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