All programmer life (about 1 year) I am tormented by the question: why do we need exception handling? Is it difficult to just use a condition? A frequent example for using exceptions in textbooks (in my case in C ++) is division by zero. When the user enters 2 numbers and, if the second (divisor) is zero, an exception is thrown. But why do you need to do this? Why can't I immediately display the text of the error and end the program (or pass it to the calling module)?
6 answers
From my own experience I can offer the following view on the choice of options using exceptions:
Wherever it is not necessary, it is NOT worth using exceptions.
The most compelling reasons are:
- Exceptions are not intended for organizing normal ways to run a program. As an example, this complicates the task (or makes it generally impossible at all) to predict the path of program execution (result: branch miss predication). Accompanying such a code also becomes a non-trivial task.
- Decreases speed. Support for the exclusion mechanism is not free, because compilers have to create add. checks and exception interceptors, support the objects of the exceptions themselves, etc. This may especially unexpectedly “shoot” on some exotic platform at the wrong time.
- Requests the user in advance to use the exception mechanism for working with your code.
- Inter-modular (i.e., beyond a binary module, for example, a DLL) passing exceptions is a bad practice. The fact is that instead of intercepting by reference, a user can use the interception of an exception object by value, which will result in a copy of the original exception object being created at the client in a completely different environment. In addition to inefficiency, it is also unsafe.
- Lack of understanding of how this mechanism works. Trite, but very vital.
"Well, when should they be used?"
Exceptions should be used in the following cases:
- It is known in advance that neither in this place of the code nor in the immediate client it is impossible to correctly handle a serious error. Then it remains to send an exception "somewhere higher", in the hope that "there" they know what to do.
- If necessary, notify the client of the inability to correctly create (initialize) an object — by throwing an exception in the constructor. On the other hand, you can initialize an object using, for example, the
Init()
function, which returns an error code, and allow the client to decide for himself whether to use exceptions.
- Points 4 and 5 need special attention. - avp 5:03 pm
- plus the answer. An example is working with the hardware, especially in drivers, when there are cases of hardware “failure”. - vv2cc
Both approaches are permissible, but the variant with exceptions can be more elegant and compact.
- Need to look at specific cases. On the one hand, dragging an error code through a chain of functions will turn into a fascinating activity that you shouldn’t do. On the other hand, there is this: if (send_sms (msg)! = OK) {if (send_email (msg)! = OK) {notification_failed (msg); }} That with exceptions will be ugly try {send_sms (msg); } catch (DeliveryFailure e) {try {send_email (msg); } catch (DeliveryFailure e2) {notification_failed (msg); }} (Crosses I remember vaguely, I could dull somewhere with the syntax.) - drdaeman
- oneWhat and speech - skegg
- oneIt would be more correct to: try {send_sms (msg); send_email (msg); } catch (DeliveryFailure e) {notification_failed (msg); } Plus, you can catch exceptions not only in the block where the function was called. ps. code doesn't want to get up normally in comments = ( - gridsane
- Here, by the way, is one of the few sensible examples here when exceptions are actually convenient. It is enough to imagine that the chain of function calls of the type send_sms (); send_email (); ... is long and there is code between calls (for example, preparation of arguments), and if an error occurs in any of these functions, it is necessary to stop calls and perform uniform actions. This is where exception handling really looks beautiful. - avp
Can. And what's more, there are two large programmer camps - some consider that exceptions should be made, others that only the return code should be checked. In reality, it is sometimes impossible to check all the conditions and it is easier to put exception handling - for example, if a third-party library code is called.
It also happens that if you do all the checks, the code turns into a set of checks.
- My programs are built on a huge number of functions. I try to make it so that when an error occurs, I can calmly put a return and exit the function. Thus, I do not need any exceptions. I just thought that without using exceptions I was losing an important thing in programming. - cheremushkin
- @cheremushkin, rather do not lose. Sometimes exceptions are convenient, sometimes they lead to a jumble of code to check what to release / close. Actually, the latter is also often when checking return codes. - avp
Exceptions are one of the most attractive means of language. You just need to learn how to use them correctly. Contrary to popular belief, the use of exceptions is much broader than the banal error handling. It is especially convenient to use them to transfer control (and, possibly, data) at once through several levels in the call hierarchy. Or not even calls, but simply nested blocks of code. The name itself as it hints at us that exceptions are intended to work with exceptional situations that are not at all obliged to be erroneous. They only have to be exceptional compared to the normal course of the program. So exceptional that it does not make sense to do a preemptive check each time.
- one@Shamov, "It is especially convenient to use them to transfer control ...", and do not play longjmp ()? Here with "They only have to be exceptional in comparison ..." I agree. - avp
- 3Yes, an excellent tool if you need to write code in which no one will ever figure it out. - beardog 1:01 pm
- 2I once wrote a parser for a homemade language. In the model with exceptions, it turned out very nicely - the parser itself parses recursively. If something is wrong - throws an exception. And it rises up along the whole chain. And these are dozens of nested calls. How to do this code with return codes - I vaguely imagine. But to make a code that throws exceptions at every step is not the same. Some compilers generate such code for exceptions that they can kill all performance. - KoVadim
- 3In one office where I worked, a very complex self-made library was used, completely built on return codes. Many of these codes grew exponentially. It often happened that the system engineers released another release, and there was only one point in the changelog: new bugs were added. New return codes were meant. All the time we happily smiled at this ambiguous phrase. And once they had to add a special function - erroneous_error (), which returned true if the previous error code should not be considered an error. - Shamov
- 2Everything can be brought to the point of absurdity. - avp 4:05 pm
Exceptions are very good. In principle, you can do without them and use standard return codes, but there are also inconveniences in using return codes. 1. With the use of exceptions, practically there will be no problems with temporary objects. Threw exceptions - all unfinished objects crashed down. And do not worry what memory to clean and so on. 2. If you need to send information about problems in the cascade call of functions from the lower level to the upper check return codes become painful and very cumbersome.
- Question under item 1: Speech about generating an exception in the constructor? - vladimir_ki
I switched to a new job, there a large amount of code was written using exceptions. When trying to reuse the code, of course they began to climb out where not needed, and generate errors. I had to rewrite the old code under the usual checks.
In general, exceptions remind me of the goto construction, only worse, because transfer control to the levels above. With a large number of exceptions, especially if the same ones are generated in different places, debugging the code is VERY difficult.
- The choice between bad code with exceptions and good code where there are no exceptions is an illusion. In reality, the choice is always whether to use a higher level of control (which, in any case, needs to be done), specifically designed exceptions for this purpose, or come up with some crutches with special return codes that allow you to slip through several levels of hierarchy. - Shamov
- oneIn the process of transition from exceptions to return codes, you should try not to allow one major error - do not mix these two methods in one module. On the other hand, nobody prevents objects that are used for exceptions from adding a couple of fields that will carry additional information. But the main plus of exceptions is that many compilers insert the output of the call stack, by which you can trace the chain of calls and find out who is to blame if the exception is not handled. In case the exception is processed at a high level , the stack may also be interesting. - KoVadim
- What are return codes? Just some of their codes and their functions for which you can track something? - nMike
- return codes are when the function returns 0, for example, in case of success, and returns -1 in case of error. Or 0 in case of error and a positive number in case of success. Either it guarantees that it sets a global variable in case of failure (
errno
). - KoVadim - 2Situations where it is enough to return just -1 in case of an error is very simple. In such cases, exceptions may not be used. And they certainly cannot be appreciated if you deal only with such cases. It is quite another thing if in case of an error you need to transfer to the top, for example, the file name. And in some cases it should be absolute, and in some cases relative. And there are several cases when you need to transfer not only the file name, but the line number in this file. - Shamov