Getting error information from catch(...)

I am managing exceptions using C++ MFC using the catch(...) option. Is there any way to get more information using this exception handler, more than just "and exception occurred"? Like Windows getLastError() or something?

Any help would be appreciated.
void myProgram
{
	CStdioFile		file;
	CString			szPath = _T("Myfile.txt");
	CString			szData,szError;
	bool			bFound = false;
	int				nErrors = 0;
	TCHAR			szCause[255];

	try
	{
		file.Open(szPath,  CFile::modeNoTruncate | CFile::modeReadWrite);
		file.SeekToEnd();
		while( file.ReadString(szData) && !bFound && !nErrors )
		{
			if( szData.Find(_T("MyName="),0) >= 0 )
			{
				someProcessProgram(szData);
				bFound = true;
			}
		}

		file.Close();

	}
	catch( CException* e )
	{
		e->GetErrorMessage(szCause,255);
		e->Delete();
		szError.Format(_T("An exception occurred while reading data.\nWindows reports: %s"),szCause);
		nErrors++;
		AfxMessageBox(szError);
	}
	catch( std::exception* e )
	{
		szError.Format(_T("An exception occurred while reading data.\nWindows reports: %s"),e->what());
		nErrors++;
		AfxMessageBox(szError);
	}
	catch(...)
	{
		szError = _T("An exception occurred while reading data.");
		nErrors++;
		AfxMessageBox(szError);
	}

}

Open in new window

TheIronDukeAsked:
Who is Participating?
 
ZoppoCommented:
Hi TheIronDuke,

to get more info about SEH exceptions you can try following:

1. Remove the 'catch(...)' within your try/catch

2. Write a wrapper function which calls you function and encapsulate the call in a __try/__except, i.e.:
void myProgramCaller()
{
	__try
	{
		myProgram();
	}
	__except( myExceptionFilter( GetExceptionInformation() ) )
	{
	}
}

Open in new window

3. Implement the 'myExceptionFilter' somehow like this:
LONG
myExceptionFilter( LPEXCEPTION_POINTERS lpExp )
{
	EXCEPTION_RECORD* pER = lpExp->ExceptionRecord;

	switch( pER->ExceptionCode )
	{
	case( EXCEPTION_DATATYPE_MISALIGNMENT ):
	case( EXCEPTION_BREAKPOINT ):
	case( EXCEPTION_SINGLE_STEP ):
	case( EXCEPTION_ARRAY_BOUNDS_EXCEEDED ):
	case( EXCEPTION_FLT_DENORMAL_OPERAND ):
	case( EXCEPTION_FLT_DIVIDE_BY_ZERO ):
	case( EXCEPTION_FLT_INEXACT_RESULT ):
	case( EXCEPTION_FLT_INVALID_OPERATION ):
	case( EXCEPTION_FLT_OVERFLOW ):
	case( EXCEPTION_FLT_STACK_CHECK ):
	case( EXCEPTION_FLT_UNDERFLOW ):
	case( EXCEPTION_INT_DIVIDE_BY_ZERO ):
	case( EXCEPTION_INT_OVERFLOW ):
	case( EXCEPTION_IN_PAGE_ERROR ):
	case( EXCEPTION_INVALID_DISPOSITION ):
	case( EXCEPTION_GUARD_PAGE ):
	case( EXCEPTION_INVALID_HANDLE ):
		return EXCEPTION_CONTINUE_SEARCH;
	case( EXCEPTION_PRIV_INSTRUCTION ):
		{
			TRACE( "Priviledged instruction" );
			return EXCEPTION_EXECUTE_HANDLER;
		}
	case( EXCEPTION_NONCONTINUABLE_EXCEPTION ):
		{
			TRACE( "None-continuable exception" );
			return EXCEPTION_EXECUTE_HANDLER;
		}
	case( EXCEPTION_ILLEGAL_INSTRUCTION ):
		{
			TRACE( "Illegal instruction" );
			return EXCEPTION_EXECUTE_HANDLER;
		}
	case( EXCEPTION_ACCESS_VIOLATION ):
		{
			TRACE( "Access violation" );
			return EXCEPTION_EXECUTE_HANDLER;
		}
	case( EXCEPTION_STACK_OVERFLOW ):
		{
			TRACE( "Stack overflow" );
			return EXCEPTION_EXECUTE_HANDLER;
		}
	case( 0xE06D7363 ):
		{
			// This exception code will be used for any error that is raised by
			// the Microsoft Visual C++ compiler through a call to "throw"
			// (see KB185294)
			TRACE( "MSC Exception!" );
			return EXCEPTION_EXECUTE_HANDLER;
		}
	default:
		{
			TRACE( "Unknown exception" );
		}
	}

	return EXCEPTION_EXECUTE_HANDLER;
}

Open in new window

(This sample comes from some real code I use in my programs)

It's important to understand what the return values mean, you'll find a description at https://technet.microsoft.com/de-de/library/security/ms679328

In short about the two I use above: EXCEPTION_CONTINUE_SEARCH causes the system to search for some catch for the exception down the stack (so i.e. an EXCEPTION_BREAKPOINT is at last passed to the debugger), EXCEPTION_EXECUTE_HANDLER causes the system to pass execution to the __except block.


Hints:

- Probably you're not interested to get info about or the way some specific exceptions are handles as I do, so take a careful look at the exceptions used in the switch/case and what they return.

- In some cases the TRACE probably isn't able to create an output, i.e. it can happen with 'stack-overflow' exception - but at least you should be able to set a breakpoint there.


Hope this helps,

ZOPPO
0
 
Manuel FloresCommented:
You could return or show the CFileException::GetErrorMessage content.
0
 
TheIronDukeAuthor Commented:
I was more interested in what I can get from the "catch(...)" exception.

CException should give me CFileException exceptions, correct? At least that's the way I understand it.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
Manuel FloresCommented:
Exactly because is an abstract class implemented by all CXXXXExceptions subclasses.

I think indeed that the way you have programmed it, i.e. using the superclass, will catch all errors.

Anyway;  you can't actually see the exception variable that is thrown when using catch(...)
0
 
Manuel FloresCommented:
Some tips from other forums;

"....This is how you can reverse-engineer the exception type from within catch(...) should you need to (may be useful when catching unknown from a third party library) with GCC:
    catch(...)
    {
        std::exception_ptr p = std::current_exception();
        std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
    }
0
 
sarabandeCommented:
Windows API wouldn't throw exceptions beside of SEH exceptions but would set the global errno variable and the last error that you could get by GetLastError. you could get the text of a non-zero error code by


//Returns the last Win32 error != 0 as message text
CString GetLastErrorAsString()
{
    DWORD errorMessage = GetLastError();
    if(errorMessage == 0)
        return ""; 

    TCHAR * messageBuffer = nullptr;
    size_t size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessage, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &messageBuffer, 0, NULL);

   CString message(messageBuffer, size);

    //Free the buffer.
    LocalFree(messageBuffer);

    return message;
}

Open in new window


if you only need the text for debugging you may look into the winerror.h which contains all the messages.


Structured Exception Handling (SEH) handles system errors like 'access violation' (what means pointer errors) or severe os errors for example if you run short of contiguous memory. you could throw SEH errors yourself but that isn't recommended (see https://msdn.microsoft.com/en-us/library/swezty51.aspx). you can catch SEH errors if you enable this in the properties for C/C++ Code Generation. then a (normal) try catch block also would catch SEH exceptions. the problem is that you hardly can recover from SEH errors and handle them. the best you can do is to show a message and exit from program.

many functions don't throw an exception but return with error. this has the advantage that you can handle the individual error immediately after the call. if the function throws an exception on error (i have even seen concepts where exceptions were thrown on success) you can catch them immediately or let another function located higher in the call stack, handle it. the problem here is that you need a very strict exception concept to be able to handle the exception exactly at a point where you can undo all that has been changed and find an alternative call which could avoid the error. if you were using a class library or a third party library you don't have  a choice. you have to use the error and exception concept given.

Sara
0
 
peprCommented:
To add...

The catch (...) catches all that was not catched above. The question is whether its usage is a good practice (unless it is a quick hack) -- excactly because of what you observe.

The MFC does not use the std::exception base class for exceptions. So, the question may be whether to catch it at all.

The CException is the base class for MFC exception; however, the catch construct is used only when the exact exception occurred (not the derived class). Consider that the +1 for the Manuel's advice.

I suggest also to read the recommendations from rather new initiative (by Stroustrup and the core guys) named C++ Core Guidelines:

E.17: Don't try to catch every exception in every function

E.18: Minimize the use of explicit try/catch
0
 
frankhelkCommented:
No comment has been added to this question in more than 21 days, so it is now classified as abandoned.

I have recommended this question be closed as follows:

Split:
-- Zoppo (https:#a41748384)
-- pepr (https:#a41748372)
-- sarabande (https:#a41747588)


If you feel this question should be closed differently, post an objection and the moderators will review all objections and close it as they feel fit. If no one objects, this question will be closed automatically the way described above.

frankhelk
Experts-Exchange Cleanup Volunteer
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.