Solved

"has triggered a breakpoint" error when closing my SDI app using the CLOSE button.

Posted on 2009-07-08
14
867 Views
Last Modified: 2013-11-20
Hi,

I know these errors can be put down to bad pointers etc, but I've been through all my code and cannot for the life of me work out why this is happening.

I have an SDI MFC app (written in VS2005) and when I close it via the 'close' button it always triggers breakpoints on exit (_after_ the onclose method in CMainFrame has been called and completed).

However, it closed absolutely fine with no errors when I use File>Exit or double click the top left of the window to close it.

Please help, is there a simple workaround for this so I can capture the close button click and make it do exactly what file>exit does instead, or are there any other quick suggestions as to what may be causing it?

Thanks in advance!

Chris J
0
Comment
Question by:chrispauljarram
  • 5
  • 5
  • 4
14 Comments
 
LVL 33

Expert Comment

by:pgnatyuk
ID: 24805551
with BoundChecker you can find the leak.
Put breakpoints into all Close and Destroy handlers to see that it works; and works only once; check that your windows do not try to handle something else after the close message.
0
 

Author Comment

by:chrispauljarram
ID: 24805707
Hi,

I don't have BoundChecker unfortautnely and can't find an evaluation copy, any other suggestions?

Cheers,
Chris J
0
 
LVL 33

Expert Comment

by:pgnatyuk
ID: 24805852
when the app stopped on the berakpoint, you can continue, right?
Than in the Output window you see a memory dump or a warning message?
Please take a look here:
http://msdn.microsoft.com/en-us/library/974tc9t1(VS.71).aspx
http://msdn.microsoft.com/en-us/library/k70yt3e2(VS.71).aspx
http://msdn.microsoft.com/en-us/library/e5ewb1h3(VS.80).aspx
I know, what you're going to say. :)
 _CRTDBG_MAP_ALLOC helped me many times.
Purify+? I know it's all not for free.
 
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24812647
>>>> and when I close it via the 'close' button

Can you post the code for OnClose() ?

The easiest closing is to post a WM_CLOSE message to the mainframe window:

     AfxGetMainWnd()->PostMessage(WM_CLOSE);

It should have the same effect than with using the 'x' or File->Exit
0
 

Author Comment

by:chrispauljarram
ID: 24814256
itsmeandnobodyelse:

Clearly File->Exit and using the 'X' do different things as stated in the question (which I'm not sure you understood?)

Thanks,
Chris J
0
 
LVL 33

Expert Comment

by:pgnatyuk
ID: 24814357
When the user presses "File->Exit" the message comes to the main frame. Right? Probably you have something like OnFileExit method.
When the user uses 'X', the message also comes to the main frame, but this time works OnClose method. Or you don't have this method?
If you don't have, let's add it. Here we will do the same as in OnFileExit. Is it possible?
 
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24814527
>>>> Clearly File->Exit and using the 'X' do different
Thank you. Yes, I thought you had a separate Close button in some form which didn't work.

So your problem is that using the 'x' doesn't do the same as double-clicking on the application icon top-left?

If so, the mainframe onclose ran in some issues which do not occur when the application was closed rather the frame.

What is strange, that File->Exit also should send a WM_CLOSE message to the main window (what is the mainframe in a SDI). So, the CMainFrame::OnClose should be called in any case.

Can you post that function? And tell where the user breaks happen?

If the OnClose wasn't called when closing with File-Exit you could do - as a workaround not as a solution -
 

    (MyApp*)AfxGetApp())->OnFileExit();

in CMainFrame::OnClose and return after that. Note, that would give an infinite loop if OnClose would be called later.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

Author Comment

by:chrispauljarram
ID: 24814961
Hi,

Thanks again for the suggestions - the OnClose() method is always called whether I use the 'x' button or file>exit, so you are right there.  The user breaks always happen at the end of the function when I call back up to CWnd::OnClose() after doing my things.  I do a bit of cleanup in the close method as well as iterate through 'User' objects which I ask one by one if the user wants to save (however the fault still ocurrs even if the userlist is empty).

The entire method body is:

void CMainFrame::OnClose()
{
      int userCount = m_pUsers->GetCount();

      for(int i = 0; i < userCount; i++)
      {
            CUser* user = (CUser*) m_pUsers->GetAt(m_pUsers->FindIndex(i));

            if(user->changed)
            {
                  sprintf(cTemp, "Do you wish to save changes to %s?", m_pUserSettingsView->getCurrentUser()->name);
                  int ret = MessageBox(cTemp, "Save User", MB_ICONQUESTION | MB_YESNOCANCEL);
                  
                  if(ret == IDYES)
                  {
                        OnSaveUser();
                  }
                  else if(ret == IDCANCEL)
                  {
                        return;
                  }
            }
      }

      mainThread.exit = true;

      // Give thread time to stop before clearing up objects and closing window.
      Sleep(1000);

      if(currentGame != NULL)
      {
            currentGame->gameClosed();
      }

      delete m_pConsole;
      m_pConsole = NULL;

      OpenIniFile();
      CIniFile::DeleteSection(OPENUSERS_SECTION_NAME, INIFILE_NAME);

      int savedUserCount = 0;

      for(int i = 0; i < m_pUsers->GetCount(); i++)
      {
            CUser* user = (CUser*) m_pUsers->GetAt(m_pUsers->FindIndex(i));

            if(user->fileName != NULL)
            {
                  sprintf(cTemp, "User%d", savedUserCount);
                  savedUserCount++;
                  CIniFile::SetValue(cTemp, user->fileName, OPENUSERS_SECTION_NAME, INIFILE_NAME);
            }

            // Save in open users list for next time (if this is a saved user).

            user->Destroy();
            delete user;
            user = NULL;
      }

      m_pUsers->RemoveAll();
      delete m_pUsers;
      m_pUsers = NULL;

      for(int i = 0; i < m_pGames->GetCount(); i++)
      {
            CGame* game = (CGame*) m_pGames->GetAt(m_pGames->FindIndex(i));
            game->Destroy();
            delete game;
            game = NULL;
      }

      m_pGames->RemoveAll();
      delete m_pGames;
      m_pGames = NULL;

      for(int i = 0; i < m_pMotionDevices->GetCount(); i++)
      {
            CNSSConfiguredMotionDevice* dev = (CNSSConfiguredMotionDevice*) m_pMotionDevices->GetAt(m_pMotionDevices->FindIndex(i));
            dev->Destroy();
            delete dev;
            dev = NULL;
      }

      m_pMotionDevices->RemoveAll();
      delete m_pMotionDevices;
      m_pMotionDevices = NULL;

      for(int i = 0; i < m_pWindDevices->GetCount(); i++)
      {
            CNSSConfiguredWindDevice* dev = (CNSSConfiguredWindDevice*) m_pWindDevices->GetAt(m_pWindDevices->FindIndex(i));
            dev->Destroy();
            delete dev;
            dev = NULL;
      }

      m_pWindDevices->RemoveAll();
      delete m_pWindDevices;
      m_pWindDevices = NULL;

      _CrtDumpMemoryLeaks();
      CWnd::OnClose();
}


The
_CRTDBG_MAP_ALLOC and _CrtDumpMemoryLeaks(); define / method have helped me clean up a few strings I had lying about - however the call to _CrtDumpMemoryLeaks(); does still result in some being shown but it does not make it obvious where. The output is as follows:

Detected memory leaks!
Dumping objects ->
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(141) : {15825} normal block at 0x036A1FE0, 25 bytes long.
 Data: <  >x            > EC 97 3E 78 08 00 00 00 08 00 00 00 01 00 00 00
{1597} normal block at 0x033E8FD0, 40 bytes long.
 Data: < IG             > 20 49 47 00 00 00 00 00 01 00 00 00 00 CD CD CD
{1308} normal block at 0x035F0FE8, 20 bytes long.
 Data: < IG             > 14 49 47 00 00 00 00 00 01 00 00 00 00 CD CD CD
{205} normal block at 0x0340BBF8, 1024 bytes long.
 Data: <0 Mph           > 30 20 4D 70 68 00 CD CD CD CD CD CD CD CD CD CD
{185} client block at 0x033E2F38, subtype c0, 192 bytes long.
a CUserSettingsView object at $033E2F38, 192 bytes long
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\plex.cpp(29) : {181} normal block at 0x033DAF80, 124 bytes long.
 Data: <      =     XO= > 00 00 00 00 90 AF 3D 03 00 00 00 00 58 4F 3D 03
{179} normal block at 0x033D6FE8, 16 bytes long.
 Data: <  0.00          > 20 20 30 2E 30 30 B0 00 CD CD CD CD CD CD CD CD
{178} client block at 0x033D4F58, subtype c0, 160 bytes long.
a CGameInfoView object at $033D4F58, 160 bytes long
{177} normal block at 0x033D2FF0, 12 bytes long.
 Data: <            > 00 00 00 00 00 00 00 00 16 02 00 00
{176} normal block at 0x033D0FE0, 24 bytes long.
 Data: <                > 96 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(141) : {172} normal block at 0x033C8FC8, 47 bytes long.
 Data: <  >x            > EC 97 3E 78 1E 00 00 00 1E 00 00 00 01 00 00 00
c:\documents and settings\chris\my documents\visual studio 2005\projects\nssdriverapp\nssdriverapp\mainfrm.cpp(56) : {169} normal block at 0x033C2BF8, 1024 bytes long.
 Data: <User0 vice3ID an> 55 73 65 72 30 00 76 69 63 65 33 49 44 00 61 6E
c:\documents and settings\chris\my documents\visual studio 2005\projects\nssdriverapp\nssdriverapp\mainfrm.cpp(21) : {168} client block at 0x033C0DE8, subtype c0, 532 bytes long.
a CMainFrame object at $033C0DE8, 532 bytes long
c:\documents and settings\chris\my documents\visual studio 2005\projects\nssdriverapp\nssdriverapp\nssdriverappdoc.cpp(16) : {167} client block at 0x033BEFA8, subtype c0, 84 bytes long.
a CNSSDriverAppDoc object at $033BEFA8, 84 bytes long
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\plex.cpp(29) : {152} normal block at 0x033A0F80, 124 bytes long.
 Data: <              9 > 00 00 00 00 00 00 00 00 00 00 00 00 90 AF 39 03
{151} client block at 0x0339EFD8, subtype c0, 32 bytes long.
a CDocManager object at $0339EFD8, 32 bytes long
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(141) : {150} normal block at 0x0339CF60, 154 bytes long.
 Data: <  >x            > EC 97 3E 78 89 00 00 00 89 00 00 00 01 00 00 00
c:\documents and settings\chris\my documents\visual studio 2005\projects\nssdriverapp\nssdriverapp\nssdriverapp.cpp(70) : {149} client block at 0x0339AF90, subtype c0, 108 bytes long.
a CSingleDocTemplate object at $0339AF90, 108 bytes long
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(141) : {147} normal block at 0x03396FE0, 23 bytes long.
 Data: <  >x            > EC 97 3E 78 06 00 00 00 06 00 00 00 01 00 00 00
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(141) : {146} normal block at 0x03394FD8, 33 bytes long.
 Data: <  >x            > EC 97 3E 78 10 00 00 00 10 00 00 00 01 00 00 00
{145} normal block at 0x03392FE8, 20 bytes long.
 Data: <      >x  >x  >x> 04 00 00 00 00 98 3E 78 00 98 3E 78 00 98 3E 78
{144} normal block at 0x03390FD8, 32 bytes long.
 Data: <$R x     /9  O9 > 24 52 1E 78 04 00 00 00 EC 2F 39 03 E8 4F 39 03
{65} client block at 0x029A7FB8, subtype c0, 64 bytes long.
a CDynLinkLibrary object at $029A7FB8, 64 bytes long
Object dump complete.
The thread 'Win32 Thread' (0xe98) has exited with code -1 (0xffffffff).
Detected memory leaks!
Dumping objects ->
{1597} normal block at 0x033E8FD0, 40 bytes long.
 Data: < IG             > 20 49 47 00 00 00 00 00 01 00 00 00 00 CD CD CD
{1308} normal block at 0x035F0FE8, 20 bytes long.
 Data: < IG             > 14 49 47 00 00 00 00 00 01 00 00 00 00 CD CD CD
Object dump complete.
The program '[2680] NSSDriverApp.exe: Native' has exited with code 0 (0x0).


These are either in files which do not belong to me or it simply doesnt say.

Could this be the problem?  Thanks for the useful information on the debug stack etc btw pgnatyuk, I'll have a good root through that when I get some time, maybe it will help shed further light on what is going on here.

Thanks :)
Chris J
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24815126
>>>> CWnd::OnClose()

You need to call CFrameWnd::OnClose();

I don't know whether that will solve the user breaks but calling CWnd::Close most likely was skipping some OnClose functions between (I will check that).

>>>> _CrtDumpMemoryLeaks();

The explicit call of that function will bring some leaks which are not really leaks but heap allocations made by static class objects. These were freed when the application terminated but not at this time. Also allocation made by the app class are reported as leaks.

0
 
LVL 33

Accepted Solution

by:
pgnatyuk earned 500 total points
ID: 24815179
Hi Chris
it says a lot. But actually you need to call this report function somewhere in ExitInstance.
Probably you have a lot of CString objects? I can be wrong, but somehow few times I fixed problems in my apps that looked like you posted now.
In my case we had few CString object declared in the cpp-files - static variables. So I just declared them as class members and cleared in the class destructors.
In your case it looks like a child window was not closed. Can you check it? Somehow stop the app before the closing?
0
 
LVL 33

Expert Comment

by:pgnatyuk
ID: 24815197
CWnd::OnClose(); - this line. Maybe it should be CFrame::OnClose()?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24815307
>>>> CWnd::OnClose most likely was skipping some OnClose functions between (I will check that).

Yes, the CFrameWnd::OnClose has an implementation which you skipped by calling CWnd::OnClose

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24815344
>>>> mainfrm.cpp(56) : {169} normal block at 0x033C2BF8, 1024 bytes long.
 Data: <User0 vice3ID an> 55 73 65 72 30 00 76 69 63 65 33 49 44 00 61 6E
>>>> nssdriverapp\nssdriverapp\mainfrm.cpp(21) : {168} client block at 0x033C0DE8, subtype c0, 532 bytes long.
a CMainFrame object at $033C0DE8, 532 bytes long
>>>> nssdriverapp\nssdriverapp\nssdriverappdoc.cpp(16) : {167} client block at 0x033BEFA8, subtype c0, 84 bytes long.

All these are normal allocations of class members where the destructor did not yet run.

You only should bother for leaks reported by the debugger at end of program.


0
 

Author Closing Comment

by:chrispauljarram
ID: 31601166
Thanks
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
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.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

707 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

15 Experts available now in Live!

Get 1:1 Help Now