[Collection] Error handling and exception handling, which one do you use?

xiaoxiao2021-03-06  115

CU-C / C Discussion Zone Essence CHINAUNIX.NET> Forum Home> Essence Home> C / C Essence> Text

Error handling and exception handling, which you http://www.chinaunix.net of use: apollolegend Posted: 2003-08-19 13:28:13

Zhang Xiaomeng January 2003 1. Introduction is a way to process the runtime error handling by the language. When you mention the wrong handling, you can probably have a wealth of experience even if you don't mention an exception, but in order to see the exception benefits, we still have to review common and non-common error handling methods. 1.1 Common error processing mode returns the value. The return value of our common functions is successful or failed, or even a failure. But the biggest problem in this approach is that if the caller does not take the initiative to check the return value, you can also be accepted by the compiler. You can't help him in C , which is another problem, that is, the overload function cannot only have different return values. There is the same parameter table, because if the caller does not check the return value, the compiler does not know which overload function should be called. Of course, this problem has nothing to do with this article, we are ready to put down. Just keep the return value may be ignored. Global status sign. For example, the system calls Errno used. Different from the return value, the global status flag can make the function's interface (return value, parameter table) is fully utilized. The function should set the value of this global variable before exiting the value or fail (including the reason), and the return value is the same as the return value, the caller should check this flag after calling, this constraint is really equally weak. The global variable also leads to another problem, that is, multi-threaded is not secure: If multiple threads assign a global variable, the caller will be very confused when checking this flag. If thread is safe, you can refer to Errno solution, which is thread safe. 1.2 Unopened processing mode setjmp () / longjmp (). It can be considered to be a remote goto statement. According to my experience, they seem to be uncommon to be used, maybe how much damage to structured programming style. In C , it should be more don't use them, because fatal weakness is longjmp () although unwinding stack (later said later), but will not call the destructor in the stack - enough fatal. For different compilers, you may be able to solve this problem by adding a compilation switch, but it is too uncommon, which will cause the program to be difficult to transplant. 1.3 Exceptions Now let's take a look at what is abnormal. For the return value and errno, it is basically not existed for anomalies. If you don't capture an exception thrown in the program, the default behavior is to cause Abort () to be called, the program is terminated (Core Dump) . Therefore, if your function throws an exception, the caller of this function or the caller of the caller, that is, on the current Call Stack, must have a place to capture this exception. The problem that objects from setjmp () / longjmp () does not exist in an abnormality. Then it is destroyed structured (for Oo Paradigms, maybe it should be destroyed?)? Obviously, you can use the correct logic after you have an abnormality, and you will break all the wrong handles to a place. Is this not better? In summary, it is approximately an exception in C to fully replace other error handling methods, but if the code is full of try / throw / catch, it is not a good thing, want to know an abnormal use skill, please stay patiently and continue to read [ Published reply] [View cu forum original] [close]

Apollolegend Reply is: 2003-08-19 13: 29: 042. Exception Syntax Here we discuss some syntax related issues. 2.1 Try Try always appears with Catch, with a TRY statement, at least one Catch () statement should be present. Try subsequent Block is possible to throw an exception. 2.2 Catch catch with a parameter, parameter type, and parameter names are specified by the program, and the name can be ignored. If this exception object is not intended to be referenced in the BLOCK subsequent Block. The parameter type can be build-in type, such as int, long, char, etc., or an object, an object pointer or reference. If you want to capture any type of exception, you can use "..." as a parameter of the Catch. Catch does not have to capture the exception thrown in the Try Block, and there is no capture to handle the previous level function processing. 2.3 Throw throw Take a type of instance, it and the relationship of catch is like a function call, catch specified ginseng, throw gives the argument. The compiler determines which Catch should be processed by the parameter type specified in Catch and the parameter type specified by catch. Throw is not necessarily to appear in the subsequent Block, it can appear in any way, as long as the Catch can capture it. Even in Catch Subsequent Block, you can continue to continue. There are two situations at this time, one is a new type of exception in THROW, which is the same as ordinary Throw. The second is to retrow the current exception. In this case, Throw can be expressed without parameters. For example: try {...} catch (int) {throw myException ("Hello Exception"); // Throw a new exception} catch (float) {throw; // Reapted the current floating point exception} 2.4 The function declaration is that a place is related to the THROW keyword, which is a function declaration. For example: void foo () throw (int); // can only throw INT anomaly void bar () "; // Do not throw any exception void baz (); // can throw any type of exception or Do not throw an exception If a function is brought with a Throw qualifier, you must also appear in the function body: void foo () throw (int) {...} There is a problem here, very hidden, even if you Written the foo () function above, specify that it can only throw int exception, and actually it may still throw other types of exceptions without being compiled: void fooat; // Error! Exception type error! Will be pointed out by the compiler ... baz (); // correct! Baz () may throw non-int abnormal and compiler can't find! } void baz () {throw float;} This situation is that if Baz () throws an exception, the code that calls foo () is strictly complied with the foo () declaration to write, then the program will abort () . This once made me very annoyed and thought that this mechanism was shaped with dummy, but it was still a solution, please refer to the question related to "Skills".

ApolloleGend Reply to: 2003-08-19 13: 32: 053. Exception Tips 3.1 How is an exception to work in order to be able to have an exception, let's take a look at how the exception handling works. 3.1.1 Unwinding Stack We know, each function call occurs, will perform the protection field register, parameter stack, create a stack for the stack for the call, which makes the stack growth. Each function is returned to restore the site, so that the stack is reduced. We use the process to restore the site during the process of restoring the site is called unwinding stack. The effect of the throw statement in an exception handling is the same as the function returns, and it also triggers unwinding stack. If Catch is not in the direct upper layer function of Throw, this unwinding process will continue until the appropriate catch. If there is no suitable catch, the last std :: undepepected () function is called, indicating that an unidentified exception is discovered, this function calls std :: terminate (), this terminate () call Abort (), the program termination ( Core dump). LONGJMP () mentioned in "Introduction" will also unwinding stack, but this is a C function, it is like Free () does not call the destructor's destructor, it doesn't know during the unwinding stack. Call the destructor of the object on the stack. This is the main difference between its abnormalities. 3.1.2 RTTI In the process of unwinding stack, the program will always try to find a "appropriate" Catch to handle this exception. As we mentioned in front of the relationship between Throw and Catch is a function of function calls and function prototypes, multiple caratches seem to be overloaded to accept different types. According to such a guess, it is the same as if you find a suitable Catch to deal with an exception to find a suitable function prototype in the process of the function overload. However, the actual situation is very difficult because the overloaded call can be determined in compilation time, and the abnormality throw is not, considering the following code: void foo () throw (int) {throw int;} void bar () { Try {foo (); Catch (int) {...} catch (float) {...}} void baz () {try {foo ();} catch (int) {...} catch (float) ) {...}} foo () is called in two places, which are captured by different Catch, so when they generate code for throw, it is impossible to indicate which catch capture, that is, said, Unable to be determined at compilation time. Still considering this example, let's take a look at how you can't determine the go of throw in compilation, how to determine during the run. In Bar (), a column Catch is aligned like CASE in the Switch statement. It is actually a series of judgment processes, check whether the current exception type meets the type specified by Catch, this dynamic, determine the type at runtime The technology is RTTI (Runtime Type Identification / Information). Deep Explore C Object Model [1] mentioned that RTTI is an abnormally processed by-product. About RTTI is a topic, here is not discussed in detail here. 3.2 Whether inherited std :: exception? Yes it is.

And std :: Exception already has some derived class, if you need to use them directly, you don't need to be defined again. 3.3 Every function must write throw ()? Despite the previous analysis, there is a vulnerability, but it is still a good habit, allows the caller to get very clear information from the head file, without turning those possibilities and code Synchronous documentation. If you provide a library, you should use catch (...) in the entrance function of the library to capture all anomalies, and the exception captured in catch (...) should be converted to one of the THROW list. Exception, this will ensure that no unexpected exception is produced. 3.4 GUARD Mode Anomaly Handling When unwinding stack, the objects on all stacks are destructed, but they don't automatically delete the objects on the stack, even although you write the delete statement in your code, it is skipped by throw, resulting in Memory leaks, or disclosure of other resources. For example: void foo () {... myclass * p = new myclass (); bar (p); ... delete p; // If Bar () throws an exception, it will not be run here! } void bar (myclass * p) {throw myException ();} For this situation, C provides std :: auto_ptr template to solve the problem. This commonly referred to as "smart pointer" is to protect the pointer in the original code to the template instance on a stack. When an unusually unwinding stack occurs, this template instance will be destructed, but in its In the designer function, the pointer will be delete, for example: void foo () {... std :: auto_ptr p (new myclass ()); bar (p.get ()); ... // delete P; // This sentence is no longer needed} void bar (myclass * p) {throw myException ();} Whether bar () throws an exception, the memory will be released as long as P is destructure. Not only for memory, the management of other resources can also be done with this method. In ACE [2], this approach is called Guard for protecting the lock. 3.5 Construction Functions and Destructor Construction Functions There is no return value, and many places are recommended to notify the caller structure failed by throwing anomalies. This is definitely a good way, but it is not very perfect. Mainly because throwing an exception in the constructor does not cause calls of the destructive function, for example: Class Foo {public: ~ foo () {} // This function will be called}; class bar {public: bar () {C_ = new char [10]; throw -1;} ~ bar () {delete c_;} // This function will not be called! Private: char * c_; foo f_;}; void baz () {}} In this example, Bar's despite the despite this, foo The destructor can still be called. Danger is C_ allocated in the constructor, since the destructor is not called to become Leak.

The best solution is also auto_ptr. After using Auto_Ptr, the BAR class declared to: class bar {public: bar () {c_.reset (new char [10]); throw -1;} ~ bar ()} // No need to delete C_! Private: auto_ptr c_; foo f_;}; do not throw an exception in the destructive function, this is clearly expressed in Thinking In C Volume 2 [3]. If a function that may throw an exception can be called in the destructuring function, it should be inside the destructor. 3.6 When using abnormalities, we have discussed most of the abnormalities, which can actually operate. What is the most headache encountered in practical applications When you use an abnormality, whether you should use an exception to fully replace other error handling methods mentioned in "Introduction"? First, you cannot use an exception to replace the return value, because the return value does not necessarily only succeed or failed, sometimes it is a selectable state, for example: if (Customer-> status () == Active) {...} Else {...} In this case, regardless of the return value, it is the normal result that the program can accept. The abnormality can only be used to express "abnormal" - is the wrong state. This seems to be obvious, but there are many more ways to be more than the actual programming. When you encounter such a situation, the first thing to consider is this principle. Second, look at whether abnormalities will play its advantages in a particular situation, and this advantage is just that other technologies are achieved (or simply reached). For example, if you are writing a complex bill logic for the telecommunications company, you certainly want to concentrate on the problem of business logic throughout the process of computing costs, rather than judge whether or not to release the front step according to the current return value. Apply resources. At this time, use an exception can make your code very clear, even if you have 100 places to apply for resources, just put them in a place to release them.

For example: BOOL bar1 (); BOOL BAR2 (); BOOL BAR3 (); BOOL FOO () {... char * p1 = new char [10]; ... if (! Bar1 ()) {delete p1; return False;} ... char * p2 = new char [10]; ... if (! bar2 ()) {delete p1; // To release all resources of the previous application delete p2; return false;} ... char * P3 = new char [10]; ... if (! Bar2 ()) {delete p1; // To release all resources of the previous application delete P2; delete p3; return false;}} This process is obviously as: Void Bar1 () Throw (int); int); void bar3 () throw (int); void foo () throw (int) {char * p1 = null; char * p2 = null; char * p3 = NULL; try {char * p1 = new char [10]; bar1 (); char * p2 = new char [10]; bar2 (); char * p3 = new char [10]; bar3 ();} catch INT) {delete p1; // Concentrately release resources delete p2; delete p3; throw;}} third, when you are not used in Thinking In C Volume 2 [3], what time is it? You should use the table, you can refer to it. Finally, it is said that it is related to the abnormal thing, but it is an assert that it is an abnormality in the development, and I quickly found that some people will use the error to define an exception. . Slightly reminding Assert's usage, very simple principles: Only for those that can be corrected by improved procedures can only be used. Return value, abnormally obviously not on one level, this is the entry knowledge of C. Linzi_tj Reply to: 2003-08-20 17:56:28 Very good article. I also confuse the use of anomalous and return value. Exception: Errors that may appear in the program. It is uncertain, such as allocating memory fail, disk space is insufficient. An exception is largely dependent on the runtime environment. Return Value: The situation that can be expected.

Threehair Reply to: 2003-08-20 18:26:52 Good!

Blue keyboard Reply to: 2003-08-23 19:00:53 The important part of the program is to handle possible various errors and exceptions

Copyright © Chinaunix.net * Please respect our labor, please indicate it from ChinaUnix. Net and author name *

转载请注明原文地址:https://www.9cbs.com/read-124612.html

New Post(0)