Hi, I've just been reading Joel Spolsky's forum and I came accross an intersting thead about exceptions, which had degenerated into a pro/anti debate. Now being a recent graduate I have always learnt the OOP way (barring a nasty course in Modula-2 during my first year, eurgh!) and like the exception route, but having thought about it, I haven't seen much code that uses them. There are a lot of tutorials and books that show simple example code which looks great, but I still have no real idea how to go about designing a project using exceptions.
I work in a small software house (five developers) and all the code is written using return codes for error detection. In fact, there is a mandate that every function must be enclosed in a try / catch(...) brace, but the catch simply logs the name of the function. This seems a very sub-par use of the mechanism to me.
I have started trying to encourage the use of exceptions more, but I am mainly ignored and overruled due to my lack of experience, my boss (who is very much a C coder) has a distrust, I think, and brushes my arguments off. I find that I am unable to argue effectively as I am unsure how a well-designed project would utilise exceptions in the best way.
So basically what this rather long-winded question is asking is, can anyone point to me to projects that show good examples of exception use. All of the projects that have looked at (admittedly not that many, e.g. log4cpp, netxx, doxygen) use exceptions only very minimally, or not at all. I guess what I'm looking for is a project that was designed from the outset to use exceptions fully.
Sorry that took so long, I have a tendency to ramble when I am tired.
Thanks for any pointers, H
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> I work in a small software house (five developers) and all the code is > written using return codes for error detection. In fact, there is a > mandate that every function must be enclosed in a try / catch(...) > brace, but the catch simply logs the name of the function. This seems > a very sub-par use of the mechanism to me.
> I have started trying to encourage the use of exceptions more, but I > am mainly ignored and overruled due to my lack of experience, my boss > (who is very much a C coder) has a distrust, I think, and brushes my > arguments off. I find that I am unable to argue effectively as I am > unsure how a well-designed project would utilise exceptions in the > best way. Dealing with anyone that has a set mind and is unwillingly to learn can be extremely exhausting, I once quit a job because of that. However, one very important task of a developer is to adapt; there is no way around adapting to other's coding-styles, designs, libraries or personalities in general. Also, there might be real reasons to not use a feature - the shame is that some people tend to not share their wisdom ... Sometimes, showing those people how this or that change makes the code better (whatever better is) will make things easier. Just keep in mind that you're not only doing development but handling humans there.
> So basically what this rather long-winded question is asking is, can > anyone point to me to projects that show good examples of exception > use. All of the projects that have looked at (admittedly not that > many, e.g. log4cpp, netxx, doxygen) use exceptions only very > minimally, or not at all. I guess what I'm looking for is a project > that was designed from the outset to use exceptions fully.
"The Example" is usually to use exceptions to escape from recursive and/or deeply nested calls, as parsers often do. Doing the same with return-values always involves a) a special return-value This is especially cumbersome when you're not eg returning a pointer that can be checked for null but a computed value: signalling that there is no value is almost impossible in many situations. b) checking that return-value Especially in nested calls, these checks sum up, make code larger and more cumbersome to maintain.
I also use exceptions for a worker-thread somewhere like this wait_start_signal(); exit_code = unknown; try process_data(); // deeply nested, can throw whenever an error occurs exit_code = finished; catch(e) exit_code = e;
> I've just been reading Joel Spolsky's forum and I came accross an > intersting thead about exceptions, which had degenerated into a > pro/anti debate. Now being a recent graduate I have always learnt > the OOP way (barring a nasty course in Modula-2 during my first > year, eurgh!) and like the exception route, but having thought about > it, I haven't seen much code that uses them. There are a lot of > tutorials and books that show simple example code which looks great, > but I still have no real idea how to go about designing a project > using exceptions.
First, of course, OO and exceptions are orthogonal. You can use exceptions in purely procedural code, and you can use other error reporting mechanisms in OO, without being any less OO.
OO probably helps in verifying the correction of programs using exceptions, since it is concerned with object state more than execution flow. Trying to verify correction using execution flow when exceptions are used is very difficult, since exceptions introduce a large number of new paths. This is less of a problem when reasoning about object state.
> I work in a small software house (five developers) and all the code > is written using return codes for error detection. In fact, there is > a mandate that every function must be enclosed in a try / catch(...) > brace, but the catch simply logs the name of the function. This > seems a very sub-par use of the mechanism to me.
Well, I don't see the use of the try/catch block, that's for sure.
IF the coding team has developped strategies for reporting errors using return codes, and they really work and are correct, then I would say that there is no need to change. But that's a big if -- most teams tend to handle errors on an ad hoc basis, which in practice means ignoring a lot of them, and mishandling a good number of those they don't ignore. If this is the case, then you need to change something in the way people are thinking anyway, and exceptions should certainly be one of the alternatives considered.
> I have started trying to encourage the use of exceptions more, but I > am mainly ignored and overruled due to my lack of experience, my > boss (who is very much a C coder) has a distrust, I think, and > brushes my arguments off.
Error handling is a difficult subject. It is normal that an organization which has a systme which works be distrustful of any change; most systems don't work that well. On the other hand, if the distrust is only because they didn't do it that way when he learned programming...
> I find that I am unable to argue effectively as I am unsure how a > well-designed project would utilise exceptions in the best way.
Probably not much differently than they use return codes:-).
In every case, the first step is deciding what errors you want to check for, and what you want to happen when you detect them. Typically, there will be a category of errors from which you cannot recover, some errors for which recovery should be handled locally, and some which cause the operation in progress to abort (for some adequate definition of "operation in progress" and "abort"). The latter are candidates for exceptions.
> So basically what this rather long-winded question is asking is, can > anyone point to me to projects that show good examples of exception > use. All of the projects that have looked at (admittedly not that > many, e.g. log4cpp, netxx, doxygen) use exceptions only very > minimally, or not at all. I guess what I'm looking for is a project > that was designed from the outset to use exceptions fully.
The problem is that it takes time for a project to mature. A project started five years ago is very less likely to use exceptions than one started today, and if it uses exceptions, is less likely to do so correctly.
-- James Kanze mailto:jka...@caicheuvreux.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
<c...@ntlworld.hideo> wrote in message <news:slrnb67kg9.ucp.ben@hideo.sprawl.bad>... > Hi, > I've just been reading Joel Spolsky's forum and I came accross an > intersting thead about exceptions, which had degenerated into a > pro/anti debate. Now being a recent graduate I have always learnt the > OOP way (barring a nasty course in Modula-2 during my first year, > eurgh!) and like the exception route, but having thought about it, I > haven't seen much code that uses them. There are a lot of tutorials > and books that show simple example code which looks great, but I still > have no real idea how to go about designing a project using > exceptions.
> I work in a small software house (five developers) and all the code is > written using return codes for error detection. In fact, there is a > mandate that every function must be enclosed in a try / catch(...) > brace, but the catch simply logs the name of the function. This seems > a very sub-par use of the mechanism to me.
It is, but some people seem to derive comfort from endlessly repeated boilerplate code. Somehow the repetition gives them a warm feeling that the rest of the junk must be ok too.
> I have started trying to encourage the use of exceptions more, but I > am mainly ignored and overruled due to my lack of experience, my boss > (who is very much a C coder) has a distrust, I think, and brushes my > arguments off.
I advise you to forget about it. This horse is dead, and if you press on you'll just annoy everyone. When you get more responsibility, then you'll be in a better position to do things as you think best.
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> Hi, > I've just been reading Joel Spolsky's forum and I came accross an > intersting thead about exceptions, which had degenerated into a > pro/anti debate. Now being a recent graduate I have always learnt the > OOP way (barring a nasty course in Modula-2 during my first year, > eurgh!) and like the exception route, but having thought about it, I > haven't seen much code that uses them. There are a lot of tutorials > and books that show simple example code which looks great, but I still > have no real idea how to go about designing a project using > exceptions.
The key to recognize is that return error codes and exceptions are both useful and valid ways of handling errors, and any well written program will undoubtedly have both. They largely serve different purposes, and using one for the other is often a costly mistake.
Lets look at the pros and cons of each (ERC = error return code) * ERCs are very inexpensive on run time performance, where as exceptions are very expensive on run time performance. * ERCs generally only carry a very small amount of information (generally between 1 and 32 bits.) They are sometimes supplemented with a global variable (errno, for example) but that is usually a bit of a hack, and usually doesn't add all that much either. * Exceptions can carry an arbitrary amount of information. * ERCs do not handle long distance error trapping (where the error is handled outside the current function.) Exceptions handle this very well indeed. Specifically, ERCs can cause problems with leaking resources due to destructors not being called. * The previous fact is most noticable in constructors. ERCs are unusable for errors in constructors. * ERCs, when systematically used, tend to spread your error handling code all over your main line code. This can be distracting for both reader and writer of the code. It can also, potentially cause exceptions to perform better in non exceptional cases. (because they don't have to handle all these extraneous if(error) cases.) * Exceptions on the other hand concentrate your code into on block designed specifically for error handling.
Given all these factors, I have a general rule I apply as to determine when to use error return codes, and when to use exceptions. I use exceptions for the kind of errors I would have to show a user, and I use error return codes for everything else. This is a rule of thumb, not an absolute rule with no exceptions (scuse the pun), but there is some specific logic behind it. When you are warning a user you don't much care about performance in the small sense. Why? Because computers are much faster than humans. If it takes you 100ms to handle an exception, which for a computer is a long time, it is, effectively instantaneous to the user -- the dialog box takes longer to draw.
By using this rule of thumb you largely eliminate the significance of the performance penalty, and get all the other extremely useful benefits for free. Examples of the kind of thing would be: out of memory; file not found; network connection down; software incorrectly installed; impossible internal software state and so forth.
It is also worth noting that many times an ERC does not really indicate an error per se, but rather an expected situation. For example, in the "find" function in the standard library, an error code is returned if the item sought is not found (the error code being the end() iterator.) This is in a sense an error code, but in another sense not. Perhaps a better example would be where one tried to open a file. An error return code might be a prompt to the program to create the file, as opposed to a serious internal state violation.
FWIW, ignorance of the usefulness of exceptions is widespread. I just completed interviewing about 20 programmers with 5-10 years experience coding C++ (and I chose those 20 for interview out of about 500 applicants). Most of them knew what exceptions were, not a one of them could give me even a scant idea of what the pros and cons of exceptions were over ERCs.
HTH.
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
nde_pl...@ziplip.com (Nom De Plume) writes: [snip]
> FWIW, ignorance of the usefulness of exceptions is widespread. > I just completed interviewing about 20 programmers with 5-10 > years experience coding C++ (and I chose those 20 for interview > out of about 500 applicants). Most of them knew what exceptions > were, not a one of them could give me even a scant idea of > what the pros and cons of exceptions were over ERCs.
[snip]
Funny. I could give you a list of what I think the pros and cons are. I don't have 10 years experience. I might have 5, if you are willing to count experience gained before my first professional job - and experience gained at jobs that were primarily C programing jobs. Perhaps ruling applicants who didn't have 5+ years of C++ programing experience on their resume was a mistake. :-)
I've never been asked about exceptions at a job interview. Nor about virtual functions, nor about the STL, nor about templates. Most of these things have been quite useful to know once I got the (C++) job(s), but I could have gotten those jobs without knowing anything about the above; I know because many of the people I worked with didn't know those things. (Yes, I *did* do some maintenence on a medium-sized project which used polymorphism and MFC aggressively. I didn't know MFC, and the other maintainer didn't have a clue what polymorphism was. Ugly.)
It's gotten to the point where I don't expect to be asked C++ questions at interviews. I expect to be asked domain specific questions. Unfortunately, I seldom know those as well as C++, but on the whole I do well at interviews.
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> Given all these factors, I have a general rule I apply as to determine > when to use error return codes, and when to use exceptions. I use > exceptions for the kind of errors I would have to show a user, and I > use error return codes for everything else. This is a rule of thumb, > not an absolute rule with no exceptions (scuse the pun), but there is > some specific logic behind it. When you are warning a user you don't > much care about performance in the small sense. Why? Because computers > are much faster than humans. If it takes you 100ms to handle an > exception, which for a computer is a long time, it is, effectively > instantaneous to the user -- the dialog box takes longer to draw.
And interesting point of view, but I'm not sure how I could apply this in my programs, which are almost exclusively large scale servers. There's no user as such, and I log ALL unusual conditions, and even a lot of usual ones.
There's another rule of thumb which might be useful: if you can recover and continue, then a return code is probably indicated. If you want to continue, you can't (generally) unwind the stack very far anyway, so the error will have to be treated locally. If the error means that you will probably have to abort the request, then an exception should very definitly be considered.
Note that this goes somewhat against your recommendation. If you ask a filename of the user, and cannot open it, you will certainly want to inform him. But if you ask him to reenter the filename, then you can recover and continue -- return code, and not exception.
Note that the recover and continue strategy often results in the so-called loop and a half, which is so difficult for those of us who insist on single entry/single exit blocks. Basically:
LOOP (* FOR max_retries *) do something EXIT IF success clean up for next pass END
> By using this rule of thumb you largely eliminate the significance of > the performance penalty, and get all the other extremely useful > benefits for free. Examples of the kind of thing would be: out of > memory; file not found; network connection down; software incorrectly > installed; impossible internal software state and so forth.
Now I'm less and less convinced.
- Out of memory: this is a difficult one. Most of the time I've seen processes run out of memory, it is because they leaked. In that case, the only possible solution is to abort and restart the process. If the out of memory is a result of an overly complex request, on the other hand, exceptions are a good solution. (My problem is that overly complex requests tend to blow the stack as well. And you can't get an exception from stack overflow.)
- File not found: see above. It really depends on what file: if it is the configuration file, for example, or a filename given in the command line, you probably have to abort the entire process: exit, not throw. On the other hand, if the user has just entered the filename, you are in the recover and continue situation -- not what C++ exceptions were designed for.
- Network connection down: depends which network connection, but at the server level, yes. If you loose the connection to the client, you definitly want to abort the request, but you almost certainly want to continue processing requests from other clients.
- Software incorrectly installed: just abort the process.
- Impossible internal software state: your program is hosed. The less it does after, the better. No exception here. (Do you want the system to convert null pointer accesses into exceptions? If so, a lot of functions which shouldn't throw, like std::swap of a basic type, might, and exception safety becomes very problamatic.)
> It is also worth noting that many times an ERC does not really > indicate an error per se, but rather an expected situation. For > example, in the "find" function in the standard library, an error code > is returned if the item sought is not found (the error code being the > end() iterator.) This is in a sense an error code, but in another > sense not. Perhaps a better example would be where one tried to open a > file. An error return code might be a prompt to the program to create > the file, as opposed to a serious internal state violation. > FWIW, ignorance of the usefulness of exceptions is widespread.
So is the opinion that exceptions solve all problems, and should be used for everything.
> I just completed interviewing about 20 programmers with 5-10 years > experience coding C++ (and I chose those 20 for interview out of about > 500 applicants). Most of them knew what exceptions were, not a one of > them could give me even a scant idea of what the pros and cons of > exceptions were over ERCs.
But does that mean that they simply always use exceptions, even when return codes are more appropriate, or that they always use return codes?
A more interesting question would be to ask them to explain some of the issues involved in exception safety. Although the last time I was interviewing, most of the candidates (all supposedly experts in OO programming with C++) didn't even know that destructors could be virtual, much less why you might want one -- one candidate actually asked me what I meant by virtual; he was unaware that the keyword existed. Obviously, with such candidates, there's no point in asking about exception safety (or the precautions to take with STL iterators, or what traits classes are, or...):-).
That was when the market was booming. Hopefully, those will be the people who are out of a job now. But I wouldn't count on it.
-- James Kanze mailto:jka...@caicheuvreux.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> The key to recognize is that return error codes and exceptions > are both useful and valid ways of handling errors, and any > well written program will undoubtedly have both.
Are you really saying good programs can't be written with just exceptions, or just error return codes?
LLeweLLyn <llewelly...@xmission.dot.com> wrote in message <news:m1u1egsruk.fsf@localhost.localdomain>... > Funny. I could give you a list of what I think the pros and cons > are.
Glad to hear it, I wish you had sent me your resume.
> I've never been asked about exceptions at a job interview. Nor about > virtual functions, nor about the STL, nor about templates. Most of > these things have been quite useful to know once I got the (C++) > job(s), but I could have gotten those jobs without knowing > anything about the above; I know because many of the people I > worked with didn't know those things.
IMHO what this goes to show is that the only thing lamer than the average C++ job applicant is the average interviewer for a C++ job. It is beyond my comprehension to think that, as Joel Splosky once said, that you would hire a magician without seeing a few of his tricks first. Of course mastery of the language is not the only thing that matters, but it should be a given. (However, I should also say that my experience applying for C++ jobs is exactly the same as yours.)
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> [...] > > Given all these factors, I have a general rule I apply as to determine > > when to use error return codes, and when to use exceptions. I use > > exceptions for the kind of errors I would have to show a user, and I > > use error return codes for everything else. This is a rule of thumb, > > not an absolute rule with no exceptions (scuse the pun), but there is > > some specific logic behind it. When you are warning a user you don't > > much care about performance in the small sense. Why? Because computers > > are much faster than humans. If it takes you 100ms to handle an > > exception, which for a computer is a long time, it is, effectively > > instantaneous to the user -- the dialog box takes longer to draw.
> And interesting point of view, but I'm not sure how I could apply this > in my programs, which are almost exclusively large scale servers. > There's no user as such, and I log ALL unusual conditions, and even a > lot of usual ones.
I suppose we must conclude different kinds of applicantations must decide when to use exceptions according to different rules.
> There's another rule of thumb which might be useful: if you can recover > and continue, then a return code is probably indicated.
You are arguing that C++ exceptions are intended for unrecoverable errors. One the one hand, C++ exceptions do not support resumption. On the other, they do support catch and try something else. On the gripping hand, they support cleanup (destructors, as well as catch). Perhaps that's the deciding factor; if you can't recover, but you must cleanup, throw an exception. If program state is too unreliable to risk cleanup, abort. If you can recover, use a return code; your second attempt at the original operation, or your alternative action will likely require the same context as the original. (I guess that's almost identical to what you say below.)
In practice I've made my best guess as to whether the error will be handled locally or remotely, using return codes for locally handled errors, and exceptions for the rest. I've erred on the side of return codes, on the grounds that it is easier to convert a return code to an exception than the reverse. I don't know how well this correlates with what I said in the previous paragraph, however. Finally, I don't have a lot of experience using them; the majority of my professional experience is in C, or in C++ without exceptions.
> If you want to > continue, you can't (generally) unwind the stack very far anyway, so the > error will have to be treated locally. If the error means that you will > probably have to abort the request, then an exception should very > definitly be considered.
> Note that this goes somewhat against your recommendation. If you ask a > filename of the user, and cannot open it, you will certainly want to > inform him. But if you ask him to reenter the filename, then you can > recover and continue -- return code, and not exception.
> Note that the recover and continue strategy often results in the > so-called loop and a half, which is so difficult for those of us who > insist on single entry/single exit blocks. Basically:
> LOOP (* FOR max_retries *) > do something > EXIT IF success > clean up for next pass > END
Perhaps you should throw an exception when the maximum number of tries has been reached. :-) (I actually don't think an exception is appropriate here; I like the the loop and a half construct, because it so frequently does just what I need. I do think a comment about the exit in the middle should be placed at the top of the loop, however.)
> > By using this rule of thumb you largely eliminate the significance of > > the performance penalty, and get all the other extremely useful > > benefits for free. Examples of the kind of thing would be: out of > > memory; file not found; network connection down; software incorrectly > > installed; impossible internal software state and so forth.
> Now I'm less and less convinced.
If you must report these kinds of things through a gui, you'll find a typical gui api often requires wading through multiple layers. I'm still not convinced exceptions are the appropriate response, but I think I can see how typical gui apis make them more tempting than they are when one needn't report such errors through a gui.
> - Out of memory: this is a difficult one. Most of the time I've seen > processes run out of memory, it is because they leaked. In that > case, the only possible solution is to abort and restart the > process.
But there may be useful/necessary cleanup action which can be done when one has run out of memory. The program still aborts in the end, but calling all the destructors in the stack unwinding may be necessary to cleanup resources like database connections, scratch files (well, in unix environments scratch files are usually unlink()ed after opening, and the OS cleans them up, but that's not true in most non-unix environments.)
> If the out of memory is a result of an overly complex > request, on the other hand, exceptions are a good solution. (My > problem is that overly complex requests tend to blow the stack as > well. And you can't get an exception from stack overflow.)
> - File not found: see above. It really depends on what file: if it is > the configuration file, for example, or a filename given in the > command line, you probably have to abort the entire process: exit, > not throw. On the other hand, if the user has just entered the > filename, you are in the recover and continue situation -- not what > C++ exceptions were designed for.
> - Network connection down: depends which network connection, but at > the server level, yes. If you loose the connection to the client, > you definitly want to abort the request, but you almost certainly > want to continue processing requests from other clients.
> - Software incorrectly installed: just abort the process.
I think this case has much in common (conceptually) with impossible internal state.
> - Impossible internal software state: your program is hosed. The less > it does after, the better. No exception here. (Do you want the > system to convert null pointer accesses into exceptions? If so, a > lot of functions which shouldn't throw, like std::swap of a basic > type, might, and exception safety becomes very problamatic.)
Here I think one should do whatever is most likely to facilitate finding the cause of the bad internal state. In a typical java environment, that means throwning an exception (just pointing out an example where I'd disagree with you :-). In a typical unix / c++ environment, abort, dump core, and load the image into the debugger. In this case you don't want to throw an exception, because (a) stack cleanup usually erases any information about where the problem was encountered, and (b) unpredictable behavior in cleanup functions may cause more problems than it solves. If the program is running on game console off of a CD-ROM, do a hex dump of the stack, and look up the addresses in your link file. Here, you don't throw an exception because you don't trust your compiler to do adequate optimization in the face of all those extra outgoing edges, and the memory you might have used for the range table has been taken up by textures and models and sounds.
I don't mention logging, reporting errors to the user, or saving the user's work because I feel that in most cases it's best concentrate on reducing the chances the user will have to encounter such a problem in the first place.
> > It is also worth noting that many times an ERC does not really > > indicate an error per se, but rather an expected situation. For > > example, in the "find" function in the standard library, an error code > > is returned if the item sought is not found (the error code being the > > end() iterator.) This is in a sense an error code, but in another > > sense not. Perhaps a better example would be where one tried to open a > > file. An error return code might be a prompt to the program to create > > the file, as opposed to a serious internal state violation.
> > FWIW, ignorance of the usefulness of exceptions is widespread.
> So is the opinion that exceptions solve all problems, and should be used > for everything.
> > I just completed interviewing about 20 programmers with 5-10 years > > experience coding C++ (and I chose those 20 for interview out of about > > 500 applicants). Most of them knew what exceptions were, not a one of > > them could give me even a scant idea of what the pros and cons of > > exceptions were over ERCs.
> But does that mean that they simply always use exceptions, even when > return codes are more appropriate, or that they always use return > codes?
It sounds to me like the interviewer was unable to determine what the heck the applicant would do when / if he got the job. Probably because the applicant himself didn't know.
At a previous job, a co-worker of mine was trying to decide if we should start using exceptions. He went around asking programmers what they thought about using exceptions. Not applicants; people who already had jobs. One common response: 'I like exceptions, because if the program crashes, you just put try{ ... } catch(...){} around everything and it stops crashing.' (The most common response was 'I'd never use them because they're too slow'.) He decided we should leave exceptions disabled.
> nde_pl...@ziplip.com (Nom De Plume) writes: > > > The key to recognize is that return error codes and exceptions > > are both useful and valid ways of handling errors, and any > > well written program will undoubtedly have both. > > Are you really saying good programs can't be written with just > exceptions, or just error return codes?
I am certainly saying good programs cannot be written without the use of error return codes. Using exceptions for all error handling of any kind would be a disaster. (In fact, the mere fact the the standard library uses ERCs in many places indicates that any program of more than a few hundred lines is almost certainly going to use ERCs.)
As to whether a good program can be written without exceptions, that is a more complex answer. Obviously for many years software was written without exceptions, and undoubtedly some of that was great software. However, I would suggest that to not use a mechanism that is so important in a language (once it has become available) shows a very poor design choice. One might look at the pyramids in Egypt today and laugh that it took all the resources of a nation fifty years to build, when we today could probably build one with a team of 1,000, and a years' effort (check out the Vegas strip if you doubt it.) But that ignores the fact that the Egyptians had grossly inferior tools, and in their context their accomplisments are remarkable. However, if you were building one today, and you refused to use back hoes, gasoline engines, or even a wheel, you'd be considered an idiot, or at best an excentric.
Refusing to use the correct tools when they are available (or being ignorant of their existence) shows poor engineering judgement.
No doubt there are some circumstances at the edges of mainstream programming where the limitations of exceptions might be sufficiently problematic that they should not be used.
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> And interesting point of view, but I'm not sure how I could apply this > in my programs, which are almost exclusively large scale servers. > There's no user as such, and I log ALL unusual conditions, and even a > lot of usual ones.
Strangely enough James I was actually thinking about you when I wrote the paragraph you quoted. I tried to hedge a little because I have been reminded on more than one occasion by reading your posts, that my programming world is not the whole programming world :-)
Yes indeed, obviously my rule of thumb doesn't work if there isn't a user, but I rarely write programs like that, so I don't have any rules of thumb for your situation.
> There's another rule of thumb which might be useful: if you can recover > and continue, then a return code is probably indicated. If you want to > continue, you can't (generally) unwind the stack very far anyway, so the > error will have to be treated locally. If the error means that you will > probably have to abort the request, then an exception should very > definitly be considered.
I don't know if I entirely buy that. An example I am thinking of a piece of software that allows the user to enter commands that amount to database transactions. An error might occur deep in the bowels of the database code indicating that the operation fails or is not valid. It seems to me an exception is indicated here, an unwind back up the stack freeing resources as you go back to the main user interface loop would be the ideal situation. There is no reason to think that the user cannot continue on with a different request.
> > I just completed interviewing about 20 programmers with 5-10 years > > experience coding C++ (and I chose those 20 for interview out of about > > 500 applicants). Most of them knew what exceptions were, not a one of > > them could give me even a scant idea of what the pros and cons of > > exceptions were over ERCs. > > But does that mean that they simply always use exceptions, even when > return codes are more appropriate, or that they always use return codes?
I don't know, I didn't see their code. I imagine they use both in some respects (probably exceptions where APIs demand it.) However that isn't the point really. What I was looking for was good judgement, and an understanding (or at least an opinion) as to which was better in which cicumstance.
> A more interesting question would be to ask them to explain some of the > issues involved in exception safety.
That would not be an interesting question as it would almost certainly be met with a blank stare.
> Although the last time I was > interviewing, most of the candidates (all supposedly experts in OO > programming with C++) didn't even know that destructors could be > virtual, much less why you might want one -- one candidate actually > asked me what I meant by virtual; he was unaware that the keyword > existed.
In fairness, I asked that question (virtual dtors) and they almost all got it right.
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
In message <m165qvqv2l....@localhost.localdomain>, LLeweLLyn <llewelly...@xmission.dot.com> writes
>> There's another rule of thumb which might be useful: if you can recover >> and continue, then a return code is probably indicated.
>You are arguing that C++ exceptions are intended for > unrecoverable errors. One the one hand, C++ exceptions do not > support resumption. On the other, they do support catch and try > something else. On the gripping hand, they support cleanup > (destructors, as well as catch). Perhaps that's the deciding > factor; if you can't recover, but you must cleanup, throw an > exception. If program state is too unreliable to risk cleanup, > abort. If you can recover, use a return code; your second attempt > at the original operation, or your alternative action will likely > require the same context as the original. (I guess that's almost > identical to what you say below.)
I think that there are other options to error handling which need consideration. In particular, using a call back can be useful for resumption. We already have a good example in the Standard C++ Library with new_handler.
-- ACCU Spring Conference 2003 April 2-5 The Conference you cannot afford to miss Check the details: http://www.accuconference.co.uk/ Francis Glassborow ACCU
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
In message <b59f4084.0303070938.38e2...@posting.google.com>, Nom De Plume <nde_pl...@ziplip.com> writes
>IMHO what this goes to show is that the only thing lamer >than the average C++ job applicant is the average >interviewer for a C++ job. It is beyond my comprehension >to think that, as Joel Splosky once said, that you would >hire a magician without seeing a few of his tricks first. >Of course mastery of the language is not the only thing >that matters, but it should be a given. (However, I >should also say that my experience applying for C++ jobs >is exactly the same as yours.)
A good knowledge of the basics + a willingness to learn is much better IMHO than a great deal of knowledge coupled with an arrogant belief that s/he knows how to do it. It cannot be a coincidence that the best C++ experts I know are also the ones that continually seek to better their knowledge and understanding.
-- ACCU Spring Conference 2003 April 2-5 The Conference you cannot afford to miss Check the details: http://www.accuconference.co.uk/ Francis Glassborow ACCU
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> > Are you really saying good programs can't be written with just > > exceptions, or just error return codes?
> I am certainly saying good programs cannot be written > without the use of error return codes. Using exceptions > for all error handling of any kind would be a disaster.
This is really a very extreme (and provably incorrect) position. I have plenty of counterexamples in my own C++ code. There are even languages like Python where exceptions are *the de-facto* way to handle errors and, in general, nobody ever uses an error return code. In Python, exceptions are even used for loop termination! Despite the fact that Python language is *interpreted* and likely to do everything including throwing exceptions more slowly than C++, people still manage to write complete applications in Python using only exceptions for error-handling.
Francis Glassborow <francis.glassbo...@ntlworld.com> wrote in message <news:mQU4CnCfXca+Ew1b@robinton.demon.co.uk>... > A good knowledge of the basics + a willingness to learn is much better > IMHO than a great deal of knowledge coupled with an arrogant belief that > s/he knows how to do it.
That is certainly true, though obviously to have both is better. However, it is my experience, both when it comes to C++ programming, and in fact life in general, that, aside from neophytes, generally speaking the people who have a thirst to learn new stuff are usually already pretty good. Programmers who have managed to get by for years without really understanding many of the fundamental concepts of programming in general and C++ language constructs in particular, rarely show any passion for learning anything new.
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> Lets look at the pros and cons of each (ERC = error return code) > * ERCs are very inexpensive on run time performance, where as > exceptions are very expensive on run time performance.
really? I thought I had read that exceptions are no worse than ERC's when the consumer is checking the ERC. In other words, correctly written ERC code, that checks the return values after each function call, may have the same performance characteristics as exception based code.
Simply enabling exceptions may code to run ever-so-slightly slower. But, removing the ERC checks may gain much of the degredation back.
joshua lehrer factset research systems NYSE:FDS
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
usenet_...@lehrerfamily.com (Joshua Lehrer) writes: > nde_pl...@ziplip.com (Nom De Plume) wrote in message <news:b59f4084.0303051236.491a03c7@posting.google.com>... >> Lets look at the pros and cons of each (ERC = error return code) >> * ERCs are very inexpensive on run time performance, where as >> exceptions are very expensive on run time performance.
> really? I thought I had read that exceptions are no worse than ERC's > when the consumer is checking the ERC. In other words, correctly > written ERC code, that checks the return values after each function > call, may have the same performance characteristics as exception based > code.
It depends entirely on the C++ implementation. On many implementations (e.g. GCC 3.x, MSVC for IA64, Sun CC, Metrowerks Codewarrior), the above "correctly written" ERC program will usually be slower than the corresponding code written to use exceptions. Actually reporting an error, on the other hand, is usually faster with ERC. If you are going to be reporting and handling an error inside your CPU-limited program's inner loop it may be more appropriate to use ERCs than exceptions.
> Simply enabling exceptions may code to run ever-so-slightly slower. > But, removing the ERC checks may gain much of the degredation back.
Or more than was lost, depending on the implementation.
"LLeweLLyn" <llewelly...@xmission.dot.com> wrote in message
news:m165qvqv2l.fsf@localhost.localdomain... > ka...@gabi-soft.de (James Kanze) writes: > > > There's another rule of thumb which might be useful: if you can recover > > and continue, then a return code is probably indicated. > > You are arguing that C++ exceptions are intended for > unrecoverable errors. One the one hand, C++ exceptions do not > support resumption. On the other, they do support catch and try > something else.
The following is one possible scenario for achieving "recover and continue" functionality with exceptions:
void actual_xyz_func(const string& filename) { FileAccess file(filename); // or DBAccess, or.. // ^-- ctor may throw BadFilenameError // do xyz with file (or db connection, or...)
}
void user_xyz_func(unsigned int level = 0) { if (level < maxtries) { string filename = read_xyz_data_from_user(); try { actual_xyz_func(filename); } catch (BadFilenameError& e) { logstream << e.what() << endl; // or show message box user_xyz_func(++level); // try again } } else { logstream << "xyz operation failed after " << tally(maxtries, "attempt") << endl; // (*) // ^-- or show message box }
}
I kind of like file access (or db access, or...) objects that throw exceptions in the ctor; the effect seems to lead to very clean "do stuff" code.
> nde_pl...@ziplip.com (Nom De Plume) writes: > > I am certainly saying good programs cannot be written > > without the use of error return codes. Using exceptions > > for all error handling of any kind would be a disaster. > > This is really a very extreme (and provably incorrect) position.
I'd be happy to see such a proof.
> I have plenty of counterexamples in my own C++ code.
Perhaps you can give us more details.
> There are even > languages like Python where exceptions are *the de-facto* way to > handle errors
I am sure you are right, but I am talking about error handling in C++ here. By no means am I saying it is impossible to write code without ERCs or exceptions, the question rather is whether it is possible to write GOOD code that way. I can't comment on whether it is possible to write good Python code without using ERCs and exceptions because I don't really know very much about Python. However, this much I know, it is good practice in Paris, France for one guy to kiss another on the cheek, however, doing the same thing in Paris, Texas is likely to get you in a whole mess of trouble.
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> David Abrahams <d...@boost-consulting.com> wrote in message <news:ur89ivv6w.fsf@boost-consulting.com>... > > nde_pl...@ziplip.com (Nom De Plume) writes: > > > I am certainly saying good programs cannot be written > > > without the use of error return codes. Using exceptions > > > for all error handling of any kind would be a disaster.
> > This is really a very extreme (and provably incorrect) position.
> I'd be happy to see such a proof.
The Boost regression test output processing program only uses exceptions for error-handling.
I didn't write this code, but people have been using it without finding bugs for quite a while. There have certainly not been any disasters due to a lack of error-return-code processing.
> > I have plenty of counterexamples in my own C++ code.
> Perhaps you can give us more details.
Take a look at any of the code with my name on the copyright in the Boost distribution. The only ERC handling you'll see there is imposed by Python's 'C' API and translated immediately into C++ exceptions.
> > There are even languages like Python where exceptions are *the > > de-facto* way to handle errors
> I am sure you are right, but I am talking about error handling > in C++ here. By no means am I saying it is impossible to write > code without ERCs or exceptions, the question rather is whether > it is possible to write GOOD code that way. I can't comment > on whether it is possible to write good Python code without > using ERCs and exceptions because I don't really know very much > about Python. However, this much I know, it is good practice > in Paris, France for one guy to kiss another on the cheek, > however, doing the same thing in Paris, Texas is likely to get > you in a whole mess of trouble.
And you're saying that it isn't GOOD to kiss another guy on the cheek in Paris, Texas?
If I understand your analogy correctly, you're implying that you can't write a GOOD C++ program without ERCs because closed-minded people may begin looking at you funny and running out to their pickups to fetch a shotgun from the rack. Or are you getting at something else?
Sorry David, I don't use cvs, and I couldn't find it in the standard boost download. However, the one regression test I did find was status/regression.cpp, and you are right, it didn't use ERCs, but it also didn't use exceptions as far as I could see (grep throw and grep catch.) Hardly surprising I suppose because obviously regression testing code is extremely atypical. So perhaps you are right, there might be a few unusual examples where error handling of any kind is not needed, or even that in some border cases that ERCs are not needed or Exceptions are not needed. However, I am talking about the types of code that is written by 99% of the C++ coding population, since that was really the subject at hand.
How exactly do you propose we modify, for example, std::find so that it doesn't use an error return code to indicate item not found? Throw an exception? What is your suggestion for mktime or mktemp or any of the other dozens and dozens of standard library functions that can return error values? Are you proposing we convert them all to throw exceptions on failure? I think that is a very bad idea indeed.
> And you're saying that it isn't GOOD to kiss another guy on the cheek > in Paris, Texas? > > If I understand your analogy correctly, you're implying that you can't > write a GOOD C++ program without ERCs because closed-minded people > may begin looking at you funny and running out to their pickups to > fetch a shotgun from the rack. Or are you getting at something else?
Good God, when did the world become so hypersensitive? I'm saying what is appropriate in one situation might not be appropriate in another. Just because it is good in Python doesn't make it good in C++.
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]
> > [...] > > > Given all these factors, I have a general rule I apply as to > > > determine when to use error return codes, and when to use > > > exceptions. I use exceptions for the kind of errors I would have > > > to show a user, and I use error return codes for everything > > > else. This is a rule of thumb, not an absolute rule with no > > > exceptions (scuse the pun), but there is some specific logic > > > behind it. When you are warning a user you don't much care about > > > performance in the small sense. Why? Because computers are much > > > faster than humans. If it takes you 100ms to handle an exception, > > > which for a computer is a long time, it is, effectively > > > instantaneous to the user -- the dialog box takes longer to draw.
> > And interesting point of view, but I'm not sure how I could apply > > this in my programs, which are almost exclusively large scale > > servers. There's no user as such, and I log ALL unusual conditions, > > and even a lot of usual ones.
> I suppose we must conclude different kinds of applicantations must > decide when to use exceptions according to different rules.
That, I think, is obvious. There is no one size fits all solution.
> > There's another rule of thumb which might be useful: if you can > > recover and continue, then a return code is probably indicated.
> You are arguing that C++ exceptions are intended for unrecoverable > errors.
Unrecoverable, in the sense that whatever I was doing cannot possibly succeed. Not necessarily that I must shut down the process.
> One the one hand, C++ exceptions do not support resumption. On the > other, they do support catch and try something else. On the gripping > hand, they support cleanup (destructors, as well as catch). Perhaps > that's the deciding factor; if you can't recover, but you must > cleanup, throw an exception. If program state is too unreliable to > risk cleanup, abort. If you can recover, use a return code; your > second attempt at the original operation, or your alternative action > will likely require the same context as the original. (I guess that's > almost identical to what you say below.)
Pretty much.
> In practice I've made my best guess as to whether the error will be > handled locally or remotely, using return codes for locally handled > errors, and exceptions for the rest. I've erred on the side of return > codes, on the grounds that it is easier to convert a return code to an > exception than the reverse. I don't know how well this correlates > with what I said in the previous paragraph, however. Finally, I don't > have a lot of experience using them; the majority of my professional > experience is in C, or in C++ without exceptions.
That corresponds to my case. I've certainly more experience without exceptions; I'd been programming for at least 25 years before I got a compiler that supported them. And I also agree that when in doubt, prefer a return code, as it is easier to convert the return code into an exception than vice versa.
> > If you want to continue, you can't (generally) unwind the stack very > > far anyway, so the error will have to be treated locally. If the > > error means that you will probably have to abort the request, then > > an exception should very definitly be considered.
> > Note that this goes somewhat against your recommendation. If you > > ask a filename of the user, and cannot open it, you will certainly > > want to inform him. But if you ask him to reenter the filename, > > then you can recover and continue -- return code, and not exception.
> > Note that the recover and continue strategy often results in the > > so-called loop and a half, which is so difficult for those of us who > > insist on single entry/single exit blocks. Basically:
> > LOOP (* FOR max_retries *) > > do something > > EXIT IF success > > clean up for next pass > > END
> Perhaps you should throw an exception when the maximum number of tries > has been reached. :-) (I actually don't think an exception is > appropriate here; I like the the loop and a half construct, because it > so frequently does just what I need. I do think a comment about the > exit in the middle should be placed at the top of the loop, however.)
It depends. The maximum number of retries is probably a good candidate for an exception; you've tried to correct and continue, and it didn't work, so I don't know what else you can do but abort the request.
I don't like the loop and a half because it violates the single entry/single exit principle, and thus makes reasoning about code correction more difficult. In practice, however, in most of the cases where it is applicable, it doesn't matter. You have stronger invariants in the second part of the loop, but the code typically doesn't depend on them.
As for signaling the fact: the loop should be small enough that one can take it in in one eyeful anyway. So why not use indentation. If I see a line in the middle of the loop that is indented like the outer body of the loop, I would certainly suppose that there was something special about it.
Still, all things considered, I prefer an extra flag (which is generally useful anyway) and a classical loop, with an if over the second part.
> > > By using this rule of thumb you largely eliminate the significance > > > of the performance penalty, and get all the other extremely useful > > > benefits for free. Examples of the kind of thing would be: out of > > > memory; file not found; network connection down; software > > > incorrectly installed; impossible internal software state and so > > > forth.
> > Now I'm less and less convinced.
> If you must report these kinds of things through a gui, you'll find a > typical gui api often requires wading through multiple layers.
Well, I wasn't suggesting that you attack the low-level API directly. In my last application, we had a status line object which registered itself for this kind of information; the actual message went to an information broker, who distributed it to whoever had registered. The source of the error had no influence in the decision as to where it was displayed.
> I'm still not convinced exceptions are the appropriate response, but I > think I can see how typical gui apis make them more tempting than they > are when one needn't report such errors through a gui.
> > - Out of memory: this is a difficult one. Most of the time I've > > seen processes run out of memory, it is because they leaked. In > > that case, the only possible solution is to abort and restart > > the process.
> But there may be useful/necessary cleanup action which can be done > when one has run out of memory. The program still aborts in the end, > but calling all the destructors in the stack unwinding may be > necessary to cleanup resources like database connections, scratch > files (well, in unix environments scratch files are usually unlink()ed > after opening, and the OS cleans them up, but that's not true in most > non-unix environments.)
It depends. In some cases, you may not want to free certain resources; a temporary file might contain vital information as to the source of the error.
> > If the out of memory is a result of an overly complex request, > > on the other hand, exceptions are a good solution. (My problem > > is that overly complex requests tend to blow the stack as well. > > And you can't get an exception from stack overflow.)
> > - File not found: see above. It really depends on what file: if it is > > the configuration file, for example, or a filename given in the > > command line, you probably have to abort the entire process: exit, > > not throw. On the other hand, if the user has just entered the > > filename, you are in the recover and continue situation -- not what > > C++ exceptions were designed for.
> > - Network connection down: depends which network connection, but at > > the server level, yes. If you loose the connection to the client, > > you definitly want to abort the request, but you almost certainly > > want to continue processing requests from other clients.
> > - Software incorrectly installed: just abort the process.
> I think this case has much in common (conceptually) with impossible > internal state.
Sort of. I think that the real difference is that you can detect it on start-up, before having acquired resources that need freeing, or having done any work which needs saving.
> > - Impossible internal software state: your program is hosed. The > > less it does after, the better. No exception here. (Do you > > want the system to convert null pointer accesses into > > exceptions? If so, a lot of functions which shouldn't throw, > > like std::swap of a basic type, might, and exception safety > > becomes very problamatic.)
> Here I think one should do whatever is most likely to facilitate > finding the cause of the bad internal state. In a typical java > environment, that means throwning an exception (just pointing out > an example where I'd disagree with you :-).
In a typical Java environement, it means creating an instance of a Throwable, and dumping the resulting stack trace to a log file before aborting. There is no need to throw the Throwable.
> In a typical unix / c++ environment, abort, dump core, and load > the image into the debugger. In this case you don't want to throw > an exception, because (a) stack cleanup usually erases any > information about where the problem was
That's a web link. You don't need CVS to follow it. You can easily browse the two .cpp files there.
> and I couldn't find it in the standard boost download. However, the > one regression test I did find was status/regression.cpp, and you > are right, it didn't use ERCs, but it also didn't use exceptions as > far as I could see (grep throw and grep catch.)
Actually you don't have to see throw and catch in the body of a program in order for it to use exceptions. The catch block is supplied by the Boost.Test library which it links with. Throws can come from various "external" sources, e.g. operator new.
> Hardly surprising I suppose because obviously regression testing > code is extremely atypical. So perhaps you are right, there might be > a few unusual examples where error handling of any kind is not > needed, or even that in some border cases that ERCs are not needed > or Exceptions are not needed. However, I am talking about the types > of code that is written by 99% of the C++ coding population, since > that was really the subject at hand.
What type of code is that? Show me a typical GUI application for which it would be "disastrous" to use exceptions for all error reporting. What kind of disaster do you anticipate?
> How exactly do you propose we modify, for example, std::find > so that it doesn't use an error return code to indicate > item not found?
That's extremely easy: do nothing to it and change your interpretation of "error condition". Nothing in the standard indicates that not finding the element is an error condition; that's interpretation you added. Using std::find is a perfectly good way to find out if an element is contained in a sequence, with the added bonus that you can manipulate the element if you found it. There's no reason to view the element's absence as an anomalous condition:
iterator p = std::find(start, finish, x); if (p != finish) p->whatever();
> Throw an exception? What is your suggestion for mktime or mktemp or > any of the other dozens and dozens of standard library functions > that can return error values? Are you proposing we convert them all > to throw exceptions on failure?
No, I am not. I am saying that there is a wide range of programs for which it is likely to be just fine to throw exceptions on all error conditions.
> > And you're saying that it isn't GOOD to kiss another guy on the cheek > > in Paris, Texas? > > > > If I understand your analogy correctly, you're implying that you can't > > write a GOOD C++ program without ERCs because closed-minded people > > may begin looking at you funny and running out to their pickups to > > fetch a shotgun from the rack. Or are you getting at something else? > > Good God, when did the world become so hypersensitive?
What's hypersensitive about my question? I am just trying to understand why you think an exceptions-only policy _must_ be "disastrous" for average C++ code when it works just fine for average Python code. It certainly can't be an efficiency issue, or none of those Python programs would exhibit acceptable performance.
[ ... ] > However, I am talking about the types of code that is > written by 99% of the C++ coding population, since that > was really the subject at hand.
Just my 2 cents:
A few months ago we (9 SW engineers) have completed the software for an ATM (Windows 2000, MSVC6.0, ~0.25Mloc). We had an exceptions only policy and the major disaster did not happen (ok, we were 10% over budget in the end but this was definitely not due to exception handling). In retrospect, I'm really glad we have chosen that path because I very much believe exceptions made live easier for us (provided that your team knows what exception safety is).
Regards,
Andreas
[ Send an empty e-mail to c++-h...@netlab.cs.rpi.edu for info ] [ about comp.lang.c++.moderated. First time posters: do this! ]