Exception Processing

 

The latest version of this topic can be found at Exception Processing.

When a program executes, a number of abnormal conditions and errors called "exceptions" can occur. These may include running out of memory, resource allocation errors, and failure to find files.

The Microsoft Foundation Class Library uses an exception-handling scheme that is modeled closely after the one proposed by the ANSI standards committee for C++. An exception handler must be set up before calling a function that may encounter an abnormal situation. If the function encounters an abnormal condition, it throws an exception and control is passed to the exception handler.

Several macros included with the Microsoft Foundation Class Library will set up exception handlers. A number of other global functions help to throw specialized exceptions and terminate programs, if necessary. These macros and global functions fall into the following categories:

  • Exception macros, which structure your exception handler.

  • Exception-throwing functions, which generate exceptions of specific types.

  • Termination functions, which cause program termination.

For examples and more details, see the article Exceptions.

Exception Macros

TRY Designates a block of code for exception processing.
CATCH Designates a block of code for catching an exception from the preceding TRY block.
CATCH_ALL Designates a block of code for catching all exceptions from the preceding TRY block.
AND_CATCH Designates a block of code for catching additional exception types from the preceding TRY block.
AND_CATCH_ALL Designates a block of code for catching all other additional exception types thrown in a preceding TRY block.
END_CATCH Ends the last CATCH or AND_CATCH code block.
END_CATCH_ALL Ends the last CATCH_ALL code block.
THROW Throws a specified exception.
THROW_LAST Throws the currently handled exception to the next outer handler.

Exception-Throwing Functions

AfxThrowArchiveException Throws an archive exception.
AfxThrowFileException Throws a file exception.
AfxThrowMemoryException Throws a memory exception.
AfxThrowNotSupportedException Throws a not-supported exception.
AfxThrowResourceException Throws a Windows resource-not-found exception.
AfxThrowUserException Throws an exception in a user-initiated program action.

MFC provides two exception-throwing functions specifically for OLE exceptions:

OLE Exception Functions

AfxThrowOleDispatchException Throws an exception within an OLE automation function.
AfxThrowOleException Throws an OLE exception.

To support database exceptions, the database classes provide two exception classes, CDBException and CDaoException, and global functions to support the exception types:

DAO Exception Functions

AfxThrowDAOException Throws a CDaoException from your own code.
AfxThrowDBException Throws a CDBException from your own code.

MFC provides the following termination function:

Termination Functions

AfxAbort Called to terminate an application when a fatal error occurs.

TRY

Sets up a TRY block.

TRY   

Remarks

A TRY block identifies a block of code that might throw exceptions. Those exceptions are handled in the following CATCH and AND_CATCH blocks. Recursion is allowed: exceptions may be passed to an outer TRY block, either by ignoring them or by using the THROW_LAST macro. End the TRY block with an END_CATCH or END_CATCH_ALL macro.

For more information, see the article Exceptions.

Example

See the example for CATCH.

CATCH

Defines a block of code that catches the first exception type thrown in the preceding TRY block.

CATCH
(exception_class, exception_object_pointer_name)  
 

Parameters

exception_class
Specifies the exception type to test for. For a list of standard exception classes, see class CException.

exception_object_pointer_name
Specifies a name for an exception-object pointer that will be created by the macro. You can use the pointer name to access the exception object within the CATCH block. This variable is declared for you.

Remarks

The exception-processing code can interrogate the exception object, if appropriate, to get more information about the specific cause of the exception. Invoke the THROW_LAST macro to shift processing to the next outer exception frame. End the TRY block with an END_CATCH macro.

If exception_class is the class CException, then all exception types will be caught. You can use the CObject::IsKindOf member function to determine which specific exception was thrown. A better way to catch several kinds of exceptions is to use sequential AND_CATCH statements, each with a different exception type.

The exception object pointer is created by the macro. You do not need to declare it yourself.

Note

The CATCH block is defined as a C++ scope delineated by braces. If you declare variables in this scope, they are accessible only within that scope. This also applies to exception_object_pointer_name.

For more information on exceptions and the CATCH macro, see the article Exceptions.

Example

   CFile* pFile = NULL;
   // Constructing a CFile object with this override may throw
   // a CFile exception and won't throw any other exceptions.
   // Calling CString::Format() may throw a CMemoryException,
   // so we have a catch block for such exceptions, too. Any
   // other exception types this function throws will be
   // routed to the calling function.
   TRY
   {
      pFile = new CFile(_T( "C:\\WINDOWS\\SYSTEM.INI"), 
         CFile::modeRead | CFile::shareDenyNone);
      ULONGLONG dwLength = pFile->GetLength();
      CString str;
      str.Format(_T("Your SYSTEM.INI file is %I64u bytes long.") , dwLength);
      AfxMessageBox(str);
   }
   CATCH(CFileException, pEx)
   {
      // Simply show an error message to the user.
      pEx->ReportError();
   }
   AND_CATCH(CMemoryException, pEx)
   {
      // We can't recover from this memory exception, so we'll
      // just terminate the app without any cleanup. Normally, 
      // an application should do everything it possibly can to
      // clean up properly and not call AfxAbort().
      AfxAbort();
   }
   END_CATCH
   // If an exception occurs in the CFile constructor,
   // the language will free the memory allocated by new
   // and will not complete the assignment to pFile.
   // Thus, our cleanup code needs to test for NULL.
   if (pFile != NULL)
   {
      pFile->Close();
      delete pFile;
   }

CATCH_ALL

Defines a block of code that catches all exception types thrown in the preceding TRY block.

CATCH_ALL
(exception_object_pointer_name)   

Parameters

exception_object_pointer_name
Specifies a name for an exception-object pointer that will be created by the macro. You can use the pointer name to access the exception object within the CATCH_ALL block. This variable is declared for you.

Remarks

The exception-processing code can interrogate the exception object, if appropriate, to get more information about the specific cause of the exception. Invoke the THROW_LAST macro to shift processing to the next outer exception frame. If you use CATCH_ALL, end the TRY block with an END_CATCH_ALL macro.

Note

The CATCH_ALL block is defined as a C++ scope delineated by braces. If you declare variables in this scope, they are accessible only within that scope.

For more information on exceptions, see the article Exceptions.

Example

See the example for CFile::Abort.

AND_CATCH

Defines a block of code for catching additional exception types thrown in a preceding TRY block.

AND_CATCH
(exception_class, exception_object_pointer_name)   

Parameters

exception_class
Specifies the exception type to test for. For a list of standard exception classes, see class CException.

exception_object_pointer_name
A name for an exception-object pointer that will be created by the macro. You can use the pointer name to access the exception object within the AND_CATCH block. This variable is declared for you.

Remarks

Use the CATCH macro to catch one exception type, then the AND_CATCH macro to catch each subsequent type. End the TRY block with an END_CATCH macro.

The exception-processing code can interrogate the exception object, if appropriate, to get more information about the specific cause of the exception. Call the THROW_LAST macro within the AND_CATCH block to shift processing to the next outer exception frame. AND_CATCH marks the end of the preceding CATCH or AND_CATCH block.

Note

The AND_CATCH block is defined as a C++ scope (delineated by curly braces). If you declare variables in this scope, remember that they are accessible only within that scope. This also applies to the exception_object_pointer_name variable.

Example

See the example for CATCH.

AND_CATCH_ALL

Defines a block of code for catching additional exception types thrown in a preceding TRY block.

AND_CATCH_ALL
(exception_object_pointer_name)  

Parameters

exception_object_pointer_name
A name for an exception-object pointer that will be created by the macro. You can use the pointer name to access the exception object within the AND_CATCH_ALL block. This variable is declared for you.

Remarks

Use the CATCH macro to catch one exception type, then the AND_CATCH_ALL macro to catch all other subsequent types. If you use AND_CATCH_ALL, end the TRY block with an END_CATCH_ALL macro.

The exception-processing code can interrogate the exception object, if appropriate, to get more information about the specific cause of the exception. Call the THROW_LAST macro within the AND_CATCH_ALL block to shift processing to the next outer exception frame. AND_CATCH_ALL marks the end of the preceding CATCH or AND_CATCH_ALL block.

Note

The AND_CATCH_ALL block is defined as a C++ scope (delineated by braces). If you declare variables in this scope, remember that they are accessible only within that scope.

END_CATCH

Marks the end of the last CATCH or AND_CATCH block.

END_CATCH  

Remarks

For more information on the END_CATCH macro, see the article Exceptions.

END_CATCH_ALL

Marks the end of the last CATCH_ALL or AND_CATCH_ALL block.

END_CATCH_ALL  

THROW (MFC)

Throws the specified exception.

THROW
(exception_object_pointer) 

Parameters

exception_object_pointer
Points to an exception object derived from CException.

Remarks

THROW interrupts program execution, passing control to the associated CATCH block in your program. If you have not provided the CATCH block, then control is passed to a Microsoft Foundation Class Library module that prints an error message and exits.

For more information, see the article Exceptions.

THROW_LAST

Throws the exception back to the next outer CATCH block.

THROW_LAST
()   

Remarks

This macro allows you to throw a locally created exception. If you try to throw an exception that you have just caught, it will normally go out of scope and be deleted. With THROW_LAST, the exception is passed correctly to the next CATCH handler.

For more information, see the article Exceptions.

Example

See the example for CFile::Abort.

AfxThrowArchiveException

Throws an archive exception.

void  AfxThrowArchiveException(int cause, LPCTSTR lpszArchiveName); 

Parameters

cause
Specifies an integer that indicates the reason for the exception. For a list of the possible values, see CArchiveException::m_cause.

lpszArchiveName
Points to a string containing the name of the CArchive object that caused the exception (if available).

AfxThrowFileException

Throws a file exception.

void AfxThrowFileException(
    int cause,  
    LONG lOsError = -1,  
    LPCTSTR lpszFileName = NULL); 

Parameters

cause
Specifies an integer that indicates the reason for the exception. For a list of the possible values, see CFileException::m_cause.

lOsError
Contains the operating-system error number (if available) that states the reason for the exception. See your operating-system manual for a listing of error codes.

lpszFileName
Points to a string containing the name of the file that caused the exception (if available).

Remarks

You are responsible for determining the cause based on the operating-system error code.

AfxThrowMemoryException

Throws a memory exception.

void AfxThrowMemoryException(); 

Remarks

Call this function if calls to underlying system memory allocators (such as malloc and the GlobalAlloc Windows function) fail. You do not need to call it for new because new will throw a memory exception automatically if the memory allocation fails.

AfxThrowNotSupportedException

Throws an exception that is the result of a request for an unsupported feature.

void AfxThrowNotSupportedException(); 

AfxThrowResourceException

Throws a resource exception.

void  AfxThrowResourceException(); 

Remarks

This function is normally called when a Windows resource cannot be loaded.

AfxThrowUserException

Throws an exception to stop an end-user operation.

void AfxThrowUserException(); 

Remarks

This function is normally called immediately after AfxMessageBox has reported an error to the user.

AfxThrowOleDispatchException

Use this function to throw an exception within an OLE automation function.

void AFXAPI AfxThrowOleDispatchException(
    WORD wCode ,  
    LPCSTR lpszDescription,  
    UINT nHelpID = 0);

void AFXAPI AfxThrowOleDispatchException(
    WORD wCode,  
    UINT nDescriptionID,  
    UINT nHelpID = -1); 

Parameters

wCode
An error code specific to your application.

lpszDescription
Verbal description of the error.

nDescriptionID
Resource ID for the verbal error description.

nHelpID
A help context for your application's help (.HLP) file.

Remarks

The information provided to this function can be displayed by the driving application (Microsoft Visual Basic or another OLE automation client application).

Example

// Sort is method of automation class CStrArrayDoc
long CStrArrayDoc::Sort(VARIANT* vArray)
{
   USES_CONVERSION;

   // Type check VARIANT parameter. It should contain a BSTR array
   // passed by reference. The array must be passed by reference; it is
   // an in-out-parameter.

   // throwing COleDispatchException allows the EXCEPINFO structure of 
   // IDispatch::Invoke() to set
   if (V_VT(vArray) != (VT_ARRAY | VT_BSTR))
      AfxThrowOleDispatchException(1001, 
         _T("Type Mismatch in Parameter. Pass a string array by reference"));

   // ...
   // ...

   return 0;
}

AfxThrowOleException

Creates an object of type COleException and throws an exception.

void AFXAPI AfxThrowOleException(SCODE sc);
void AFXAPI AfxThrowOleException(HRESULT hr); 

Parameters

sc
An OLE status code that indicates the reason for the exception.

hr
Handle to a result code that indicates the reason for the exception.

Remarks

The version that takes an HRESULT as an argument converts that result code into the corresponding SCODE. For more information on HRESULT and SCODE, see Structure of COM Error Codes in the Windows SDK.

AfxThrowDaoException

Call this function to throw an exception of type CDaoException from your own code.

void AFXAPI AfxThrowDaoException(
    int nAfxDaoError = NO_AFX_DAO_ERROR,  
    SCODE scode = S_OK); 

Parameters

nAfxDaoError
An integer value representing a DAO extended error code, which can be one of the values listed under CDaoException::m_nAfxDaoError.

scode
An OLE error code from DAO, of type SCODE. For information, see CDaoException::m_scode.

Remarks

The framework also calls AfxThrowDaoException. In your call, you can pass one of the parameters or both. For example, if you want to raise one of the errors defined in CDaoException::nAfxDaoError but you do not care about the scode parameter, pass a valid code in the nAfxDaoError parameter and accept the default value for scode.

For information about exceptions related to the MFC DAO classes, see class CDaoException in this book and the article Exceptions: Database Exceptions.

AfxThrowDBException

Call this function to throw an exception of type CDBException from your own code.

void AfxThrowDBException(
    RETCODE nRetCode,  
    CDatabase* pdb,  
    HSTMT hstmt);  

Parameters

nRetCode
A value of type RETCODE, defining the type of error that caused the exception to be thrown.

pdb
A pointer to the CDatabase object that represents the data source connection with which the exception is associated.

hstmt
An ODBC HSTMT handle that specifies the statement handle with which the exception is associated.

Remarks

The framework calls AfxThrowDBException when it receives an ODBC RETCODE from a call to an ODBC API function and interprets the RETCODE as an exceptional condition rather than an expectable error. For example, a data access operation might fail because of a disk read error.

For information about the RETCODE values defined by ODBC, see Chapter 8, "Retrieving Status and Error Information," in the Windows SDK. For information about MFC extensions to these codes, see class CDBException.

AfxAbort

The default termination function supplied by MFC.

void  AfxAbort(); 

Remarks

AfxAbort is called internally by MFC member functions when there is a fatal error, such as an uncaught exception that cannot be handled. You can call AfxAbort in the rare case when you encounter a catastrophic error from which you cannot recover.

Example

See the example for CATCH.

See Also

Macros and Globals
CException Class