none
try...catch doesn't catch an exception after AfxThrowMemoryException() RRS feed

  • Question

  • Hi all.

    I have source code with Serialize:

     

        // myObjectsList is CList object
    	CMemFile memFile;
    
    	TRY
    	{
    		CArchive ar( &memFile, CArchive::store );
    		long count = myObjectsList.GetCount();
    		ar << count;
    
    		POSITION pos = myObjectsList.GetHeadPosition();
    		while( pos != NULL )
    		{
    			MyObject* myObject = myObjectsList.GetNext( pos );
    			int nType = myObject->GetType();
    			ar << nType;
    			myObject->Serialize( ar );
    		}
    		ar.Close();
    	}
    	CATCH_ALL( pE )
    	{
            ...
    		return false;
    	}
    	END_CATCH_ALL
    
    ######
    MyObject::Serialize(ar)
    {
    	CObject::Serialize( CArchive& ar );
    	if(ar.IsStoring())
    	{
    		ar << all my class variables
    	}
    	else
    	{
    		ar >> all my class variables
    	}
    }
    

     

    When I serialize a very big CList (3000-4000 objects) I have situation "No memory":

     

    // file ...\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\filemem.cpp
    void CMemFile::GrowFile(SIZE_T dwNewLen)
    {
      ...
      // allocate new buffer
      BYTE* lpNew;
      if (m_lpBuffer == NULL)
      	lpNew = Alloc(dwNewBufferSize);
      else
    	lpNew = Realloc(m_lpBuffer, dwNewBufferSize);
    
      if (lpNew == NULL)
    	AfxThrowMemoryException();
      ...
    }
    
    But very often my block TRY...CATCH_ALL doesn't catch the exception after AfxThrowMemoryException();

    For example: I run my code 3-4 times. For 2-3 tests my block TRY...CATCH_ALL catchs this exception, but for 1-2 cases the block didn't catch

     

    -------------------------------------------------------

    Additional  info:

    1) I try build my code with keys  /EHsc and /EHa too, but the issue was reproduced again

    2) In debug mode I set breakpoint on AfxThrowMemoryException():

    - for good test Call stack was

    MyCode.dll!CMemFile::GrowFile(unsigned long dwNewLen=209735656) Line 153	C++
    MyCode.dll!CMemFile::GetBufferPtr(unsigned int nCommand=1, unsigned int nCount=4096, void * * ppBufStart=0x0012ef4c, void * * ppBufMax=0x0012ef48) Line 385 C++
    MyCode.dll!CArchive::Write(const void * lpBuf=0x258c3438, unsigned int nMax=716) Line 512 + 0x2a bytes C++
    MyCode.dll!CArchive::operator<<<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t> > >(const ATL::CStringT<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t> > > & str="Война и мир


    MyCode.dll!MyObject::SerializeMap(CArchive & ar={...}, CMap<unsigned long,unsigned long,CStringList *,CStringList * &> & map={...}) Line 175 C++
    MyCode.dll!MyObject::Serialize(CArchive & ar={...}) Line 261 C++
    MyCode.dll!MyObjectFactory::DoSerialize(CList<CXObject *,CXObject *> & pObjects={...}, long & dwSize=0, unsigned char * & pBuf=0x00000000) Line 181 + 0x1c bytes C++
    and after "Step Over" AfxThrowMemoryException() a programm expands the stack to my catch section

    - for issue case: I had call stack as in good test, but after "Step Over" I was again on AfxThrowMemoryException(). If I try call AfxThrowMemoryException() again then I had call stack

    MyCode.dll!CMemFile::GrowFile(unsigned long dwNewLen=209735656) Line 153	C++
    MyCode.dll!CMemFile::GetBufferPtr(unsigned int nCommand=1, unsigned int nCount=4096, void * * ppBufStart=0x0012ef4c, void * * ppBufMax=0x0012ef48) Line 385	C++
    MyCode.dll!CArchive::Flush() Line 557 + 0x2a bytes	C++
    MyCode.dll!CArchive::Close() Line 360	C++
    MyCode.dll!CArchive::~CArchive() Line 314	C++
    MyCode.dll!_CallSettingFrame(unsigned long funclet=1241000, unsigned long pRN=259, unsigned long dwInCode=1927035260) Line 73	Asm
    MyCode.dll!__FrameUnwindToState(EHRegistrationNode * pRN=0x0012efa8, void * pDC=0x0012e5f0, const _s_FuncInfo * pFuncInfo=0x0845c738, int targetState=1) Line 1149	C++
    MyCode.dll!CatchIt(EHExceptionRecord * pExcept=0x0012e61c, EHRegistrationNode * pRN=0x0012efa8, _CONTEXT * pContext=0x0012e63c, void * pDC=0x0012e5f0, const _s_FuncInfo * pFuncInfo=0x0845c738, const _s_HandlerType * pCatch=0x0845c6f4, const _s_CatchableType * pConv=0x0844a424, const _s_TryBlockMapEntry * pEntry=0x0845c704, int CatchDepth=0, EHRegistrationNode * pMarkerRN=0x00000000, unsigned char IsRethrow=0) Line 1259 + 0x17 bytes	C++
    MyCode.dll!FindHandler(EHExceptionRecord * pExcept=0x0012e61c, EHRegistrationNode * pRN=0x0012efa8, _CONTEXT * pContext=0x0012e63c, void * pDC=0x0012e5f0, const _s_FuncInfo * pFuncInfo=0x0845c738, unsigned char recursive=0, int CatchDepth=0, EHRegistrationNode * pMarkerRN=0x00000000) Line 774 + 0x31 bytes	C++
    MyCode.dll!__InternalCxxFrameHandler(EHExceptionRecord * pExcept=0x0012e61c, EHRegistrationNode * pRN=0x0012efa8, _CONTEXT * pContext=0x0012e63c, void * pDC=0x0012e5f0, const _s_FuncInfo * pFuncInfo=0x0845c738, int CatchDepth=0, EHRegistrationNode * pMarkerRN=0x00000000, unsigned char recursive=0) Line 524 + 0x25 bytes	C++
    MyCode.dll!__CxxFrameHandler3(EHExceptionRecord * pExcept=0x7c9032a8, EHRegistrationNode * pRN=0x0012e61c, void * pContext=0x0012efa8, void * pDC=0x0012e63c) Line 365 + 0x1f bytes	C++
    ntdll.dll!7c90d80a()
    [Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]	
    ntdll.dll!7c90327a()
    ntdll.dll!7c92a8c3()
    ntdll.dll!7c91a1ba()
    ntdll.dll!7c90e48a()
    kernel32.dll!7c812afb()
    kernel32.dll!7c812afb()
    ntdll.dll!7c915bbd()
    kernel32.dll!7c812afb()
    MyCode.dll!_realloc_dbg(void * pUserData=0xe06d7363, unsigned int nNewSize=1, int nBlockUse=3, const char * szFileName=0x0012e990, int nLine=1239792) Line 973 + 0x1b bytes	C++
    MyCode.dll!_CxxThrowException(void * pExceptionObject=0x0012e9ac, const _s__ThrowInfo * pThrowInfo=0x0844a3f4) Line 161	C++
    MyCode.dll!AfxThrowMemoryException() Line 222	C++
    MyCode.dll!CMemFile::GrowFile(unsigned long dwNewLen=209735656) Line 155	C++
    MyCode.dll!CMemFile::GetBufferPtr(unsigned int nCommand=1, unsigned int nCount=4096, void * * ppBufStart=0x0012ef4c, void * * ppBufMax=0x0012ef48) Line 385	C++
    MyCode.dll!CArchive::Write(const void * lpBuf=0x258c3438, unsigned int nMax=716) Line 512 + 0x2a bytes	C++
    MyCode.dll!CArchive::operator<<<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t> > >(const ATL::CStringT<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t> > > & str="Война и мир
    
    
    MyCode.dll!MyObject::SerializeMap(CArchive & ar={...}, CMap<unsigned long,unsigned long,CStringList *,CStringList * &> & map={...}) Line 175	C++
    MyCode.dll!MyObject::Serialize(CArchive & ar={...}) Line 261	C++
    MyCode.dll!MyObjectFactory::DoSerialize(CList<MyObject *,MyObject *> & pObjects={...}, long & dwSize=0, unsigned char * & pBuf=0x00000000) Line 181 + 0x1c bytes	C++
    

     

    I can't find the root cause: why try...catch section can't catch AfxThrowMemoryException() in the second case

     

    Thursday, April 21, 2011 9:00 AM

Answers

  • It seems that destructor of CArchive causes further exceptions. The documentation recommends using Abort. Try this scheme:

     

    TRY

    {

        CArchive ar(. . .);

        TRY

        {

            . . .

            return true;

        }

        CATCH_ALL

        {

            ar.Abort();

            THROW_LAST();

        }

        END_CATCH_ALL()

    CATCH_ALL

    {

        memFile.Abort();

        . . .

        return false;

    }

    END_CATCH_ALL()

     

    • Marked as answer by Stobor Monday, April 25, 2011 11:02 AM
    Monday, April 25, 2011 9:20 AM

All replies

  • realloc means that it reallocate memory blocks. So when you memory size is not change. It just allocate memory again at the same address just like free().

    Monday, April 25, 2011 7:51 AM
  • It seems that destructor of CArchive causes further exceptions. The documentation recommends using Abort. Try this scheme:

     

    TRY

    {

        CArchive ar(. . .);

        TRY

        {

            . . .

            return true;

        }

        CATCH_ALL

        {

            ar.Abort();

            THROW_LAST();

        }

        END_CATCH_ALL()

    CATCH_ALL

    {

        memFile.Abort();

        . . .

        return false;

    }

    END_CATCH_ALL()

     

    • Marked as answer by Stobor Monday, April 25, 2011 11:02 AM
    Monday, April 25, 2011 9:20 AM
  • It seems that destructor of CArchive causes further exceptions.  


    Possibly the stack is being corrupted.

    Stobor: as an incidental comment, in your code fragment

     POSITION pos = myObjectsList.GetHeadPosition();
    while( pos != NULL )
    {
    MyObject* myObject = myObjectsList.GetNext( pos );

    is it possible that you are not handling the first element in the list?  In other words, what does myObject represent after the call to GetHeadPosition() followed by GetNext()?  The first element, or the second one?

    Also, is there any particular reason that you are using the MFC macros rather than the C++ exception handling keywords? If there isn't, consider Converting from MFC Exception Macros.


    Answering policy: see profile.
    Monday, April 25, 2011 10:41 AM
  • No, handling in this case is correct. Stack actually unfolded as corrupted, but I could not find the reason of it. I tried variant from Viorel_ and the issue was not reproduced
    Monday, April 25, 2011 11:02 AM
  • I tried to check the destructors, but checked only my classes. I used your variant and the issue was not reproduced Thanks.
    Monday, April 25, 2011 11:03 AM