C++ Exceptions as part of general programme flow

Like most programmers - at least of my mediocre skill level! - I am a bit shy of using exceptions. I am never comfortable using try/catch/throw and testing for them after each function. However I certainly can see the utility. Rather than - often quite clunkily - having to 'manhandle' a function so aside form its natural return value and type it will also somehow have a way to indicate that something went wrong inside it's flow. Nonetheless it feels... wrong to me and having read quite a few opinion pieces here and on other blogs and sites it seems this is a common misperception.

My case in point is a simple dynamic array class I am working on to practice using templates. I have an 'Index(const int iIndex)' member function, along with an overloaded 'operator[](const int iIndex)' to allow the array to be interrogated. They return a reference type so it can be used both for read and write operations. Admittedly I learned this technique from Herb Schildt and I have lately heard his books and ideas are not to be followed too blindly!!! However accepting this method for the moment, the obvious problem here is - what if the user mistakenly passes the function an index value which is either below zero or above the current allocated size? As the functions return references they cannot return nullptr to signal this error. Therefore the only way I can think of telling the user he has made a mistake - as I do not want at this stage to start learning about iterator objects - is to throw an exception if the index argument is out of bounds.

However, as I mentioned - somehow this feels... Wrong. SO I suppose my question is - is it okay to use exceptions in this everyday way, where they function almost as an EXPECTED part of the programme flow?
Last edited on
where they function almost as an EXPECTED part of the programme flow?
I doubt that out of bound access is a part of everyday container use. Exceptions are good exactly for that: errors which you know can happens, but should not with cautionous use.

Look at the standard library containers: they provide both unchecked access: fast, line raw arrays, if you pass wrong index, you on your own. And checked: .at() member, throws exception if you pass wrong index.
I see your point MiiNiiPaa. Also, I suppose the 'programming contract' I have read some author's talking about is that as a class provider you do everything to ensure it works properly on YOUR side of black box. The end user cannot really expect you to totally insulate him from his own errors - and indeed by using exceptions then to extent you ARE providing a graceful way to recover from a mistake.

I don't know if you ever did any retro programming back on the eighties - usually 8-Bit - 'home' computers MiiNiiPaa? But in those days, at least on the Atari 8-Bits the idea of 'defensive programming' was promoted in the magazines very widely. However nowadays it seems this concept is considered counter-productive and by effectively 'hiding' that an error has happened you are not making the programming job as a whole any easier.

I guess structured exceptions are a way of getting the best of both worlds; you defend your side of the contract from accidental errors, yet still give the end user a bit of a chance to respond rather than dropping directly to a GPF.
Last edited on
The use of exceptions is one of those hot-button triggers that you will find with programmers.

The purpose of exceptions is to catch some condition that is exceptional -- that is, it catches something that is not expected to happen nearly as often as normal flow.

What that does not mean is that you can never use exceptions for handling errors. You most certainly can.
What you describe is clearly a bug. That means the program is already in an undefined state. I'd say that getting out with an exception is ok in this case. Maybe plus an entry in a log file.
I've often seen exception classes used like so:
throw LogException << "Some Error Message";
Where LogException is a macro used to create an object which writes to a console, file, notifies a networked listener and implements std::exception::what(),
MANY, many thanks for these answers chaps!!! They do give me a lot of confidence in 'jumping in' with the exception mechanism. Although the over-riding message seems to be 'don't use them blindly', which is always good advice anyway!

I think there are two factors which in the past put me off. Firstly the syntax is VERY alien. To me it doesn't 'look like c/c++'. As part of this, at least until you get used to it the code does seem a little messy. An example of what I mean might be:

1
2
3
if(iIndex<1 || iIndex>m_iCount-1){
    throw ERROR::INDEX_OUT_OF_BOUNDS;
}


Obviously using a strongly-typed enum for an error constant is very basic and in future I will learn how to define a dedicated exception class. However what I am trying to illustrate is... how STRANGE that combination of standard C++ 'if(){}' looks with the 'something else' of 'throw'. But I suppose I will get used to it.

Secondly - and I have read this MANY times in articles on exceptions - is how they introduce new and potentially confusing return paths through the code. However, if I am properly understanding the 'finally' construct I think some of that can be ameliorated.
Last edited on
They do give me a lot of confidence in 'jumping in' with the exception mechanism.
no

is how they introduce new and potentially confusing return paths through the code.
exactly

You may use throw in very exceptional cases as the last exit (which might be very well a design flaw).
Keep in mind that each throw disturbs the program flow and hence is hard to manage
I doubt that out of bound access is a part of everyday container use. Exceptions are good exactly for that:
by using exceptions then to extent you ARE providing a graceful way to recover from a mistake.
What you describe is clearly a bug. That means the program is already in an undefined state. I'd say that getting out with an exception is ok in this case.

I have a different opinion on this case (out of bounds error). I'd abort the program and cause a core dump.

An out of bounds error usually indicates a programming bug, not a condition in the input or environment that should be dealt with. It's very unlikely that any catch block will properly deal with a coding error. Instead, the exception will dutifully unwind the stack, destroy objects, and in general obliterate any trace of what was happening when the error occurred. Thus, if you do have an out-of-bounds error, you won't know where or how to fix it.

In contrast, if you dump core, the problem will most likely be trivial to find and fix. Sure it's no fun for your users, but if you through an exception as a result of a coding bug, chances are very high that the program will end up crashing or become unstable anyway.
Hi,

Here is a link that Disch posted recently.

http://www.parashift.com/c++-faq-lite/exceptions-avoid-two-return-types.html


Check out the error processing for a basic calculator: using exceptions vs return values.

There is plenty of good stuff in the article: not all of it is about return codes.

I read somewhere that exceptions should be used whenever an object doesn't do what it's advertised to do.

There are lots of topics about exceptions on this forum. Have a go with the search function at the top of the page.

Hope my 2 cents worth helped a bit :+)

Edit:

@dhayden

I can't help thinking that your suggestion might be alright during debugging, but aborting the whole program on a live system is the very thing that should be avoided at all costs.

The article above talks about fixing bugs as a must do over using exceptions, which is I guess what you are saying. But if one can't fix the bug in the client code, then shouldn't an exception be provided anyway?

Edit 2:

I should point out that I am investigating exceptions too: I am just relating what I have gathered so far.
Last edited on
I can't help thinking that your suggestion might be alright during debugging, but aborting the whole program on a live system is the very thing that should be avoided at all costs.

Perhaps it makes sense to have a compile time switch that enables an exception vs aborting, but the problem is that once the error occurs, there's a good chance that you won't be able to recover from it. It's basically saying "write some code that will recover from a bug in your code."

There are certainly things you might be able to do: save the users work, abort the current transaction and set up to accept another one, etc. It depends on the situation. I guess my main point is that with an out-of-bounds exception, what you're likely to catch is not an error, but a bug, and recovering from a bug is very hard.
"write some code that will recover from a bug in your code."
Incorrect.

Let's say somebody wrote a library which loads a "file" and does something to it.
What should it do if file cannot be found?
Should it give a message "You entered nonexisting file moron" to user and prompt to enter new file?
Should it log that occurence, send mail to support and regenerate file from defaults?
Should it crash because if you cannot find executable itself, something gone wrong?

You throw exception to let other code decide what to do. Code which might not be written by you.

Perhaps it makes sense to have a compile time switch that enables an exception vs aborting
Assert? Crashes when debugging, dissapears from code completely in release mode.

with an out-of-bounds exception, what you're likely to catch is not an error, but a bug
It might be an associative container, and exception is the way to tell "wrong request". The thing is: you should not decide for user of your library what to do. If they want, they can leave it uncatched. Or they might have more imagination and make a situation where it could be used. Maybe they want to catch it to create a meaningful and helpful error message or write error in log file.
All this has me thinking about pre & post conditions: who has the responsibility to check pre conditions? The client code so they don't cause problems; also the objects' code again so an exception can be thrown in the case that the input is bad?

The Post conditions seem an easy enough concept - leave the object in a valid state no matter what, and provide return values in the appropriate range.

Then I started to think about Scott Meyers' point about making code hard to use wrongly. He had an example of providing a class for each month of the year, so that a Date class would be used without ambiguity.

For me, I have a function which takes Latitudes & Longitudes as parameters. Rather than having these parameters as doubles, then checking their validity and making sure they are in radians, instead I make the parameters CLatLong objects.

The CLatLong object has the responsibility to validate the values it holds and it also has a member which is in radian units. This way the CLatLong would throw an exception - why should we do anything much with a Latitude of -900.0 ?

Hopefully this means my function could provide a strong(?) guarantee that it won't throw - well at least in terms of the input anyway, I would need to investigate anything else that might potentially go wrong.

@dhayden
I wonder: did you see this bit?

theIdeasMan wrote:
The article above talks about fixing bugs as a must do over using exceptions, which is I guess what you are saying. But if one can't fix the bug in the client code, then shouldn't an exception be provided anyway?


I agree with you - one must fix bugs. I can't help thinking on the other hand that one should provide exceptions for other things that go wrong.


Hope all is well with everyone :+)
Yes, it's an excellent point that you want code that is hard to use wrongly.
Topic archived. No new replies allowed.