C which exceptions to throw
If no match is found, the control flow continues to unwind the stack until the next try block, and so on. If a match is found, the control flow jumps to the matching catch block. As the control flow moves up the call stack, destructors are invoked for all objects with automatic storage duration that are constructed, but not yet destroyed, since the corresponding try-block was entered, in reverse order of completion of their constructors.
If an exception is thrown from a destructor of a local variable or of a temporary used in a return statement, the destructor for the object returned from the function is also invoked. Variant members of union-like classes are only destroyed in the case of unwinding from constructor, and if the active member changed between initialization and destruction, the behavior is undefined. If the exception is thrown from a constructor that is invoked by a new-expression , the matching deallocation function is called, if available.
If any function that is called directly by the stack unwinding mechanism, after initialization of the exception object and before the start of the exception handler, exits with an exception, std::terminate is called. Such functions include destructors of objects with automatic storage duration whose scopes are exited, and the copy constructor of the exception object that is called if not elided to initialize catch-by-value arguments.
If an exception is thrown and not caught, including exceptions that escape the initial function of std::thread , the main function, and the constructor or destructor of any static or thread-local objects, then std::terminate is called.
It is implementation-defined whether any stack unwinding takes place for uncaught exceptions. When rethrowing exceptions, the second form must be used to avoid object slicing in the typical case where exception objects use inheritance:. The throw-expression is classified as prvalue expression of type void. Like any other expression, it may be a sub-expression in another expression, most commonly in the conditional operator :. Create account Log in.
Namespaces Page Discussion. Views View Edit History. From cppreference. Keywords Escape sequences. Namespace declaration. Namespace aliases. Fundamental types Enumeration types Function types.
Compound types Union types. Default initialization Value initialization Zero initialization Copy initialization Direct initialization. Expressions Value categories Order of evaluation. Operators Operator precedence. Class declaration Constructors this pointer. In the real world, the code that detects a problem must typically propagate error information back to a different function that will handle the problem.
The information about the problem needs to get propagated all the way back to f1 , because only f1 has enough context to actually know what should be done about the problem. Only the code that detects the error, f10 , and the code that handles the error, f1 , have any clutter. Here is the equivalent code that uses return codes:. Functions f2 through f9 have explicit, hand-written code related to propagating the error condition back up to f1.
That is badness:. But if you instead open your eyes to the big picture, you will see a substantial difference in all the functions in between. Conclusion: one of the benefits of exception handling is a cleaner, simpler way to propagate error information back to the caller that can handle the error. When you use return codes, you often need two or more distinct return values: one to indicate that the function succeeded and to give the computed result, and another to propagate the error information back to the caller.
But then we have a problem: handling errors. Adding numbers could cause overflow, dividing could cause divide-by-zero or underflow, etc. Think of exceptions as a separate return type that gets used only when needed. So we just define all the exceptions and throw them when needed:.
But if we use return codes instead of exceptions, life gets hard and messy. The point of this is that you normally have to muck up the interface of functions that use return codes, particularly if there is more error information to propagate back to the caller. None of this clutter happens with exceptions. Here is a simple example: function f is suppoesd to call functions g , h , i and j , in sequence, as shown below.
If any other error occurs, f is to propagate the error information back to the caller. Using return codes instead of exception clutters this to the point where it is difficult to see the relatively simple algorithm. Contrast that with the version that used exceptions, which is almost self-documenting — the basic functionality is very obvious. The message is that exception handling is worth it. The benefits outweigh the costs. Fortunately there is plenty of wisdom and insight on the proper use of exceptions.
Exception handling is not new. The industry as a whole has seen many millions of lines of code and many person-centuries of effort using exceptions. The jury has returned its verdict: exceptions can be used properly, and when they are used properly, they improve code.
This FAQ gives you a list of some of those wrong mindsets. Sometimes you will do the exact opposite of what they recommend — do not write me about some situation that is an exception no pun intended to one or more of them — I guarantee that there are exceptions.
They are guidelines, and there are exceptions to each. For instance, you might put a try block around just about every call:. In general, it is bad form. If that is you, there is still hope: get a mentor. Style is sometimes caught, not just taught. The best way to signal constructor failure is therefore to throw an exception. Note: if a constructor finishes by throwing an exception, the memory associated with the object itself is cleaned up — there is no memory leak.
There is some fine print on this topic, so you need to keep reading. Write a message to a log-file. Terminate the process. Or call Aunt Tilda. But do not throw an exception! For example, if someone says throw Foo , the stack will be unwound so all the stack frames between the. During stack unwinding, all the local objects in all those stack frames are destructed.
The easy way to prevent this is never throw an exception from a destructor. But if you really want to be clever, you can say never throw an exception from a destructor while processing another exception.
So the whole solution is harder to write. That is, never throw an exception from a destructor. By the way, if you think your Fred class is going to be allocated into a smart pointer, be nice to your users and create a typedef within your Fred class:. Instead use an object of some string -like class. For example, suppose you want to get a copy of a string, fiddle with the copy, then append another string to the end of the fiddled copy. The array-of- char approach would look something like this:.
Why not just use an object of some string class? In fact, you can throw anything you like. That begs the question then, what should you throw? If possible, you should throw instances of classes that derive ultimately from the std::exception class.
Here, a temporary of type MyException is created and thrown. In fact, you have all the flexibility that you have in declaring function parameters, and the rules for whether a particular exception matches i. Given all this flexibility, how do you decide what to catch? Avoid catching by value, since that causes a copy to be made and the copy can have different behavior from what was thrown.
Only under very special circumstances should you catch by pointer. Same goes for any framework: when in Rome, do as the Romans. Feedback will be sent to Microsoft: By pressing the submit button, your feedback will be used to improve Microsoft products and services.
Privacy policy. Skip to main content. This browser is no longer supported. Download Microsoft Edge More info. Contents Exit focus mode. Is this page helpful?
Yes No. Any additional feedback? Skip Submit. Submit and view feedback for This product This page. View all page feedback.
0コメント