C++ exception handling catch of... introduce

  • 2020-04-02 01:35:45
  • OfStack

What if you want to make a catch block capable of catching exception objects of multiple data types? The C++ standard defines a special catch usage: "catch(...)". ".
Perceptual knowledge

1, the catch (...). After all is a what kind of east east, come to perceptual understanding first!
Here's an example:


 int main() 
{ 
try 
{ 
cout << " in  try block  In the ,  Prepare to throw an exception ." << endl; 
//Here an exception is thrown (where the exception object has an int of value 1)
throw 1; 
} 
//catch( int& value ) 
//Notice the catch statement here
catch(  ... ) 
{ 
cout << " in  catch( ... ) block  In the ,  Throw the int The exception object of type is handled " << endl; 
} 
}

2. Haha! An exception of type int is caught (...) Caught, here's another example:

 int main() 
{ 
try 
{ 
cout << " in  try block  In the ,  Prepare to throw an exception ." << endl; 
//Here an exception is thrown (where the data type of the exception object is double and the value is 0.5)
throw 0.5; 
} 
//catch( double& value ) 
//Notice the catch statement here
catch(  ... ) 
{ 
cout << " in  catch( ... ) block  In the , double An exception object of type is also handled " << endl; 
} 
}

3. Similarly, the double type exception object is also caught (...). The piece was captured. Yes, the catch (..) Exception objects of all data types are matched successfully, including the exception objects of all native data types provided by the C++ language, such as int, double, and pointer types such as char* and int*, as well as array types. All custom abstract data types are also included. The routine is as follows:

 int main() 
{ 
try 
{ 
cout << " in  try block  In the ,  Prepare to throw an exception ." << endl; 
//An exception is thrown here (where the data type of the exception object is char*)
char* p=0; 
throw p; 
} 
//catch( char* value ) 
//Notice the catch statement here
catch(  ... ) 
{ 
cout << " in  catch( ... ) block  In the , char* An exception object of type is also handled " << endl; 
} 
} 
int main() 
{ 
try 
{ 
cout << " in  try block  In the ,  Prepare to throw an exception ." << endl; 
//Here an exception is thrown (where the exception object's data type is int[])
int a[4]; 
throw a; 
} 
//catch( int value[] ) 
//Notice the catch statement here
catch(  ... ) 
{ 
cout << " in  catch( ... ) block  In the , int[] An exception object of type is also handled " << endl; 
} 
}

4. For exception objects of abstract data types. The catch (...). Also valid, the routine is as follows:

 class MyException 
{ 
public: 
protected: 
int code; 
}; 
int main() 
{ 
try 
{ 
cout << " in  try block  In the ,  Prepare to throw an exception ." << endl; 
//Here an exception is thrown (where the exception object's data type is MyException)
throw MyException(); 
} 
//catch(MyException& value ) 
//Notice the catch statement here
catch(  ... ) 
{ 
cout << " in catch( ... ) block In the , MyException The exception object of type is handled " << endl; 
} 
}

To catch (...). A little confused?
1. What is the catch? What's the confusion? Let's see an example first!

void main() 
{ 
int* p = 0; 
try 
{ 
//Note: the following statement, while not a throw statement, causes the system to execute
//A storage protection error exception (access violation exception.)
*p = 13; // causes an access violation exception; 
} 
catch(...) 
{ 
//The catch (...). To capture the access violation exception exception?
cout << " in catch( ... ) block In the " << endl; 
} 
}

What happens when the above program runs? The catch (...). To capture system in the access violation exception exception? Friends! Like our hero, ah yu, test it yourself!

The result? In fact, it has two different running results. When running this little program with VC under Windows 2000 system, it can be found that the program can output "catch(...)". The "block" statement is on the screen, that is, catch(...). Successfully captured live access violation in system exception is unusual, very much! But if the same program is compiled with GCC under Linux and runs, it will crash and print the error message "segment fault" on the screen.

Hero a yu a bit urgent, also began to be a bit confused, why? Why is that? Why does the same program behave differently on two different systems? The reason is: For this kind of abnormal system because of a hardware or operating system (for example, zero page in addition to the abnormal, memory, storage control, error, etc.), window2000 system has called a Structured Exception Handling (Structured Exception Handling, SEH), the mechanism of this thing is too much, it can and good combination of VC in the c + + Exception Handling model (c + + Exception Handling model of VC implementation actually build largely on SEH mechanism, or it is an extension of the SEH, Later articles will elaborate on and analyze this long-known SEH, see catch(...). How to magically take over the flow of program control after the system exception occurs, but that's all in the future. Under Linux, system exceptions are controlled by signal processing programming methods (signal processing programming, signal processing progamming). How under Unix and Linux programming books, there are detailed in the signal processing programming is introduced, persistent character, of course, o fool sure it won't let go, can deep into the signal processing inherited from the Unix programming internal implementation mechanism, and try to improve it, make it can also be well and c + + exception handling model combining).

How does the C++ standard explain the different results of the same program? Here it is important to note that Windows 2000 system under catch(...) The ability to catch system exceptions is a complete extension of itself. This is not required in the C++ standard; it only says catch(...). You must be able to catch all exceptions thrown by the throw statement in your program. Therefore, the above program runs under Linux system and the result is fully compliant with the C++ standard. Although we must also admit that Windows 2000 system under the C++ exception handling model of this extension is a very good perfect, greatly improved the security of the program.

Why do we use catch(...)? This guy?
Programmer friends might say, is there any question? Didn't we cover it at the beginning of this article? The catch (...). The ability to capture multiple data types of exception objects gives the programmer a better control over the exception objects and makes the developed software system more reliable. Therefore, a more experienced programmer will usually write its code modules in the following way:


 void Func() 
{ 
try 
{ 
//The program code here does the really complex calculations, and it's in the middle of execution
//It is possible to throw exception objects of types DataType1, DataType2, and DataType3.
} 
catch(DataType1& d1) 
{ 
} 
catch(DataType2& d2) 
{ 
} 
catch(DataType3& d3) 
{ 
} 
//Notice the DataType1, DataType2, and DataType3 that may be thrown in the try block above
//Each type of exception object already has a catch block to handle it. But why
//There is also a catch(...) defined at the end. Block? This is for better security and
//Reliability, to avoid the result when the above try block throws other unconsidered exception objects
//The sequence has the serious consequence of an unexpected crash, and this is especially effective on systems developed with VC because
//To catch (...). Can catch system exceptions, and system exceptions are often a headache for programmers, now
//Systems are often complex and co-developed by many people, which can lead to one if not carefully developed
//The pointer variable points to another illegal region, and an unexpected disaster unfortunately occurs. The catch (...). For this
//Potential pitfalls provide an effective remedy.
catch( ... ) 
{ 
} 
}

In addition, in order to make the developed system more reliable, VC programmers often add a top-level trycatch block to the entry function of application programs (such as CXXXApp::InitInstance()) and the entry function of worker threads, and use catch(...). To catch all exceptions, as follows:

 BOOL CXXXApp::InitInstance() 
{ 
if (!AfxSocketInit()) 
{ 
AfxMessageBox(IDP_SOCKETS_INIT_FAILED); 
return FALSE; 
} 
AfxEnableControlContainer(); 
// Standard initialization 
// If you are not using these features and wish to reduce the size 
// of your final executable, you should remove from the following 
// the specific initialization routines you do not need. 
#ifdef _AFXDLL 
Enable3dControls(); // Call this when using MFC in a shared DLL 
#else 
Enable3dControlsStatic(); // Call this when linking to MFC statically 
#endif 
//Note that there is a top level trycatch block and use catch(...) To catch all exceptions
try 
{ 
CXXXDlg dlg; 
m_pMainWnd = &dlg; 
int nResponse = dlg.DoModal(); 
if (nResponse == IDOK) 
{ 
// TODO: Place code here to handle when the dialog is 
// dismissed with OK 
} 
else if (nResponse == IDCANCEL) 
{ 
// TODO: Place code here to handle when the dialog is 
// dismissed with Cancel 
} 
} 
catch( ... ) 
{ 
//Dump some important information about the system and notify the administrator to find out the reason for the unexpected exception.
//At the same time, find ways to restore the system, such as restarting the application, etc
} 
// Since the dialog has been closed, return FALSE so that we exit the 
// application, rather than start the application's message pump. 
return FALSE; 
}

From the above routines and analysis, it can be concluded that due to catch(...) Can catch exception objects of all data types, so use catch(...) where appropriate. It does make software systems more reliable. This is really where people use catch(...) This is the best reason. But don't get me wrong: in the C++ exception handling model, catch(...) isn't the only catch(...) Method can catch almost any type of exception object.


Related articles: