return ERROR vs throw Exception
-
Hello.
I have read a lot of information about how to determine the way function should report when something goes wrong. But I still do not completely understand the situation and need a simple method to determine what should I choose: return special value or throw an exception.
Another question: when the function should convert (from return value to exceptions, for example) the errors it get from functions it calls?
-
Exceptions are good for external interfaces of i.e. libraries. For example if you have some kind of sophisticated array class, it may throw an "index out of bound exception" if the user of the array-class tries to read/write beyond the bounds of the array.
And they are particularly interesting if you want to trigger the deallocation of resources allocated by the RAII mechanism in case of error (i.e. if some error occurs in the ctor of a class (where you can't return error codes anyway)).
Returning error codes is most interesting for detecting internal errors hidden somewhere in the implementation or for slim interfaces and simple functions where the C++ exception mechanism would cause unnecessary overhead.
-
Tachyon schrieb:
Returning error codes is most interesting for detecting internal errors hidden somewhere in the implementation or for slim interfaces and simple functions where the C++ exception mechanism would cause unnecessary overhead.
I think it isn't a good choice...
I can forgot the check agains Errorcodes. I can't forgot exceptions...
In C++ exceptions are for errorhandling. If you have an error throw it, if you have an state, return it.cu André
-
asc schrieb:
Tachyon schrieb:
Returning error codes is most interesting for detecting internal errors hidden somewhere in the implementation or for slim interfaces and simple functions where the C++ exception mechanism would cause unnecessary overhead.
I think it isn't a good choice...
I can forgot the check agains Errorcodes. I can't forgot exceptions...
In C++ exceptions are for errorhandling. If you have an error throw it, if you have an state, return it.cu André
Nope. You should use exception with care and only if they make sense.
See "Scott Meyers: More Effictive C++" Item 14 & 15
-
asc schrieb:
If you have an error throw it, if you have an state, return it.
I have read another thing: "If the error suppose continue of program then you should return a value. If the error usually suppose program termination then you should throw an exception".
But if I have two types of errors in the single function?
For example, I have readFromFile() method of my class. It can be two types of errors: "can not open file" and "not enough memory for loading this file". Does this mean that I should return error in first case and throw an error in the second case in the single function?
-
SAn schrieb:
asc schrieb:
If you have an error throw it, if you have an state, return it.
I have read another thing: "If the error suppose continue of program then you should return a value. If the error usually suppose program termination then you should throw an exception".
But if I have two types of errors in the single function?
For example, I have readFromFile() method of my class. It can be two types of errors: "can not open file" and "not enough memory for loading this file". Does this mean that I should return error in first case and throw an error in the second case in the single function?
I think, that is a case, where both errors are critical for your application. You should raise appropriate exceptions here.
There is a quasi official rule that says "Use exceptions for critical errors that cannot be ignored. Use error codes if the error isn't severe and may be ignored."
-
SAn schrieb:
I have read another thing: "If the error suppose continue of program then you should return a value. If the error usually suppose program termination then you should throw an exception".
I mean with an error something that must be handled.
-
I am writing a library which working with special file format (from scientific equipment). The library should provide a way to work with raw data and to work with this format as structured storage.
When working with data as with structured storage user can:
- Check structure of storage (function returns bool)
- Get pointer to data (and data size) by data identifier (id). Function returns NULL, if data with such id is not found, and throws an exception if structure of storage is bad.
- Get list of all identifiers for data in storage. Throws an exception if structure of storage is bad.
- Add data, specifying its id and size. The function returns pointer to newly allocated data. The problem is that I can not decide what the function should do when data with such id is already exists. It can be 3 possibilities: 1) return NULL 2) return pointer to existing data 3) throw an exception. What is your advice?
- Delete data, specifying its id. What function should do if the data with such id is not found? Return false or throw an exception?
-
ad 4) I think one question that you should ask yourself is whether you want to put emphasis on correctness or ease of use. If you fancy correctness then throw an exception if the key (id) already exists. If you want ease of use, just replace the data, or, if you prefer that, return the pointer to the old data (without replacing it in the file). The latter is what std:
:insert does IIRC, but I always found it to be a little strange.
ad 5) Again, correctness or ease of use. Correctness calls for an exception, ease of use calls for "just do nothing".
p.S.: "ease of use" might not be entirely correct for what I mean, however I can't think of a better word. I'm not referring to a flat learning curve, but to a design that let's you write very compact code, by eleminating the need to have "does key X exist" checks in some places.
p.p.S.: personally I'd throw an exception in both situations.
-
hustbaer schrieb:
If you want ease of use, just replace the data, or, if you prefer that, return the pointer to the old data (without replacing it in the file). The latter is what std:
:insert does IIRC, but I always found it to be a little strange.
if you want to replace the value, you can always use operator[], which in fact returns a reference to a (possibly newly created) object on which you can in turn apply operator= to change its state. now, this would not be possible if insert replaced - no matter the circumstance - the actual object.
as for the problem with which you are confronted, you can always check wether an insertion actually took place by
if (your_map.insert(make_pair(key, value)).second) ...
-
In general:
- if it is no extra work, use return codes.
- if you implement time-critical functions (such as graphic processing), use return codesSome considerations:
1. depending on the compiler, exceptions can be expensive.
2. an advantage of exceptions is, that they can rescue you in a situation where you hit an unexpected situation which you do not know how to handle. Particularly, if you are not prepared (by design) to query all return codes through a number of nested function calls, a throw operation automatically returns directly to the location where the first catch is found, thus ignoring all intermediate frames on the calling-stack. Thats very convenient, BUT:
3. that way, exceptions mercilessly ignore all houskeeping attempts. i.e.: everything which was allocated dynamically until the "throw" is still there when the exception was fired. That means, that all new pointers which have been allocated in between the "throw" and the "catch" event are lost such causing eventual memory leaks.On the other hand, exceptions provide an elegant way to make libraries safe in utilization. If, for example, you write a library which will be used in situations which you cannot influence or by developers which you do not know, than exceptions might be the solution of choice: they can't be ignored by developers as opposed to return codes.
There is no simple answer to the question "exceptions or return codes".
I personally avoid exceptions. In case that i cannot abuse returncodes for such situations (e.g. because i want to return pointers or references or other useful things), and i have the problem to be in a deeply nested function where an unforeseen situation occurs, I use to use global state information such as "errno". Such information can be queried wherever you want and let you still use return values for more useful things.
-
emax schrieb:
1. depending on the compiler, exceptions can be expensive.
That's propably true but you should keep in mind that exceptions usually appear very rarely. So if one occurs, you normally don't mind the little loss of CPU-time.
emax schrieb:
3. that way, exceptions mercilessly ignore all houskeeping attempts. i.e.: everything which was allocated dynamically until the "throw" is still there when the exception was fired. That means, that all new pointers which have been allocated in between the "throw" and the "catch" event are lost such causing eventual memory leaks.
That's true either but with heavily using RAII (like smart-pointers or auto-destructing containers) that is no problem at all.
So when you write your code carefully I can't see any reason to avoid exceptions for the matter of performance or memory-leaks.
-
Badestrand schrieb:
emax schrieb:
1. depending on the compiler, exceptions can be expensive.
That's propably true but you should keep in mind that exceptions usually appear very rarely. So if one occurs, you normally don't mind the little loss of CPU-time.
Thats not a statement of its own, please regard my context:
emax schrieb:
- if you implement time-critical functions (such as graphic processing) ...
And BTW: what is a "little loss"? A loop running for 800000 Pixels? The TO asked for a general approach of error handling. And in general, exceptions are more expensive than return codes.
If you ever use C++ on other platforms than x86, notably the AS/400, you will see _extreme_ differences in runtime, even if the throw/catch code parts are not even hit. Exception handling is a matter of overall performance, not of "local" performance.
Badestrand schrieb:
emax schrieb:
3. that way, exceptions mercilessly ignore all houskeeping attempts. i.e.: everything which was allocated dynamically until the "throw" is still there when the exception was fired. That means, that all new pointers which have been allocated in between the "throw" and the "catch" event are lost such causing eventual memory leaks.
That's true either but with heavily using RAII (like smart-pointers or auto-destructing containers) that is no problem at all.
To me, the TOs question indicates low experience in C++ programming. If he would know about boost, the GoF and other advanced technologies, he most likely wouldn't have asked. My answer is supposed to help the questioner, not to demonstrate skills.
Basestrand schrieb:
So when you write your code carefully
Yes. If.
Badestrand schrieb:
I can't see any reason to avoid exceptions for the matter of performance or memory-leaks.
You can. See above.
-
emax schrieb:
To me, the TOs question indicates low experience in C++ programming.
So if someone's learning to drive a car, it's better to tell him not to use the motor, instead of teaching him how to drive safely?
-
No.
The best is, to tell him never to drive slower than 200mph, even in cities during rush-hour.
-
So, you are saying, to use technique A safely, you need to make use of technique B. Since the OP has no experience with technique B, he shouldn't use any of them at all?
(Regarding memory leaks: The first advice _anyone_ gets when using raw pointers or arrays, in this forum, is "use vector" or "use smart pointers" etc. So this can't be too advanced to learn early. In fact, IMHO it is more complicated to cope with raw memory directly in a safe way than putting raw memory in RAII classes)
The other extreme, "the 200 mph driver", would be to use exceptions at all possible occasions, which - of course - can't be any good as well.
-
emax schrieb:
what is a "little loss"? A loop running for 800000 Pixels?
The "little loss" was related to the exception-throw. If you throw and catch exceptions in such a loop then there seems to be something wrong with the design
emax schrieb:
The TO asked for a general approach of error handling. And in general, exceptions are more expensive than return codes.
Not in gerenal, especially when you want to achieve the same functionality.
emax schrieb:
If you ever use C++ on other platforms than x86, notably the AS/400, you will see _extreme_ differences in runtime, even if the throw/catch code parts are not even hit.
Ok. I expected he develops for an x86-platform where unused try-catch-blocks almost don't (if at all) influence the performance. So it might be (and believing your post it is) different for other platforms.
emax schrieb:
To me, the TOs question indicates low experience in C++ programming. If he would know about boost, the GoF and other advanced technologies, he most likely wouldn't have asked.
I think that safe memory-management is one of the most important things to learn in C++ so if he doesn't know about smart-pointers then now it's the time to learn
-
The TO asked for a "simple" answaer, which i didn't deliver. The oppsoite is true. I weighed advantages against disadvantages, and there is nothing wrong with that.
I gave a "personal" advice. If you gurus think that my advice is wrong, you may give a different one.
It's up to the TO to decide.
Not much more to say.
-
Wieso ist der Thread denn plötzlich wieder offen? Der wurde doch bereits geschlossen!?!
-
Thread closed because of spam the continous spam.
Humans
please continue here: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1523116.html
BR
VinzenzTachyon schrieb:
Wieso ist der Thread denn plötzlich wieder offen? Der wurde doch bereits geschlossen!?!
Weil ich den temporär geschlossen hatte. Für vielleicht 2 minuten. Aber da hier noch aktiv geschrieben wurde hab ich den zunächst offen gelassen. Naja hoffe das diese Lösung jetzt besser funktioniert.