Exceptions, Go to Hell!

T

thomas

Hi,

Sometimes I found it very convenient to use STL in my application.

But one thing I hate is that STL containers throw exceptions. Because
we handle errors explictly in our application, we don't want
exceptions.

I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

Specifically, will the following operation throw exceptions? How to
handle it without the "try, catch" clause?
 
G

Goran Pusic

Hi,

Sometimes I found it very convenient to use STL in my application.

But one thing I hate is that STL containers throw exceptions. Because
we handle errors explictly in our application, we don't want
exceptions.

Solution to that conundrum is to wrap each and every operation with
STL into a try/catch and return error code equivalent to caught
exception (or whatever you use to signal errors) from catch.

And if you do use STL, you can't e.g. rig operator new to return null
on failure, because that will cause your code to invoke UB if
allocation inside an STL container fails.
I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

Specifically, will the following operation throw exceptions? How to
handle it without the "try, catch" clause?

Fair enough :). Hard call for a question like yours.

Answer is: no. STL does not function correctly without exceptions, and
so do most part of standard C++ library. For example, STL's interface
depends on exceptions to function. Look at:

some_vector.push_back(data);

Imagine, now, that copy ctor of data's type throw. What do you do?
Imagine, further, that re-allocation, that might be needed, fails. How
would you signal that? STL is simply not made for that. To correctly
handle various failure modes in generic containers, but _without_
exceptions, you need _entirely_ different interface.

Apart from that, constructors (e.g. your string example) need
exceptions, and operator overloading needs exceptions.

(Strong personal opinion follows) Conclusion: there is __absolutely no
C++ without exceptions__. Put up or get out :).

Or... There is, if you rig memory allocation failure to e.g. terminate
your process, so that you can say that this failure doesn't happen :)
(not in the spirit of C or C++ languages, that move). And if you
abstain from using pretty much any C++ library. And if you can
guarantee that at least no copy constructor of any type you use can
have a failure mode. (and there's probably more conditions I can't
think about).

IOW, you're doing it wrong©, because C++ without exceptions is a crime
against humanity. (Which is not to say that specifically-crafted
parts, e.g. particularly perf. demanding, low-level code, or code
exposed to outside world through shared libraries, can't or shouldn't
be exceptions-free).

Darn... I didn't resist the urge not to speak in favor of exceptions,
did I? :)

Goran.
 
A

Andrea Venturoli

Il 08/24/10 08:38, thomas ha scritto:
I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

Your compiler might have a switch for this.
Of course the STL won't work as expected, then, as it is supposed to
throw exceptions.
Specifically, you will never know if it fails.


Specifically, will the following operation throw exceptions?

Possibly, unless you turn exceptions off in the compiler.


How to handle it without the "try, catch" clause?

No way: if you turn off exceptions, you are putting your head in the
sand, just hoping it won't fail.


(Don't teach me the benefits of exceptions)

I won't. It's just that if you want to use a library which uses
exceptions, you have to use exceptions.



bye
av.
 
Ö

Öö Tiib

Hi,

Sometimes I found it very convenient to use STL in my application.

But one thing I hate is that STL containers throw exceptions. Because
we handle errors explictly in our application, we don't want
exceptions.

Only part of container interface may throw exceptions. If it is not
true for you then it is that implementation you use.
I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

STL does throw on bugs. If you do not have bugs then it does not
throw. If there is extension (like microsofts secure iterators) then
use methods of extension.
Specifically, will the following operation throw exceptions? How to
handle it without the "try, catch" clause?

Without the "try, catch" clauses. You "handle errors explictly in our
application" so the exceptions never happen.

This is programming bug. What should you do? (hint: "catch it" is
wrong answer)
 
I

Ian Collins

Hi,

Sometimes I found it very convenient to use STL in my application.

But one thing I hate is that STL containers throw exceptions. Because
we handle errors explictly in our application, we don't want
exceptions.

I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

Maybe, but how will you know if a failure that is reported by an
exception occurs?
 
S

Stuart Redmann

thomas said:
Hi,

Sometimes I found it very convenient to use STL in my application.

But one thing I hate is that STL containers throw exceptions. Because
we handle errors explictly in our application, we don't want
exceptions.

I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

That would be quite nice. Unfortunately, C++ offers no language
feature that turns off exceptions globally. Microsoft's COM framework
uses a language-independent scheme for working with exceptions which
may come close to what you want: Exceptions in COM is basically
managed via return values; every method returns an integer error code
(in order to get the actual exception object with all the detailed
information, you'll have to query COM's run-time environment). Even
though this scheme takes the freedom of choosing the return type of a
method, COM lets you declare a "retval" parameter. When you use the
COM method in client code, the MS's Visual C compiler generates two
methods: one that uses the usual error code as return value and one
that acts like a wrapper: it will translate the usual error code to
exceptions and will return the "retval" parameter. This is quite handy
since it is up to you which method you want to use.

Regards,
Stuart
 
S

Stuart Redmann

Hi,

Sometimes I found it very convenient to use STL in my application.

But one thing I hate is that STL containers throw exceptions. Because
we handle errors explictly in our application, we don't want
exceptions. [snip]
I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

Specifically, will the following operation throw exceptions? How to
handle it without the "try, catch" clause?
[snip]

Goran said:
Answer is: no. STL does not function correctly without exceptions, and
so do most part of standard C++ library. For example, STL's interface
depends on exceptions to function. Look at:

some_vector.push_back(data);

Imagine, now, that copy ctor of data's type throw. What do you do?
Imagine, further, that re-allocation, that might be needed, fails. How
would you signal that? STL is simply not made for that. To correctly
handle various failure modes in generic containers, but _without_
exceptions, you need _entirely_ different interface.
[snip]

That's a good argument. I guess that nobody wants to establish a
scheme for propagating errors for containers other than the exception
mechanism because such a scheme would be quite ugly. Unfortunately, C+
+ does provide little support for exception specifications inside
templates: There is no way how I can tell C++ that the type inside
some container will not throw any exceptions at all, so that the
interface of the fully typed container will only expose those
exceptions that stem from the container code. For example, if I have a
type T which may throw an exception E when being copy-constructed, I'd
expect that std::vector<T> has an exception specification like this:
std::vector<T>::push_back (T&) throw (E, out_of_memory_exception).
If I use a type U that throws no exceptions upon copy-construction,
this should be
std::vector<U>::push_back (U&) throw (out_of_memory_exception)
[This is quite probably very wrong, but you get the idea].
Were we able to change the exception specification depending on a
template parameter, we could change STL's vector::push_back interface
in such a way that it could only return error codes for errors that
occur due to the implementation of vector::push_back, like
EPushBackError vector<T>::push_back (T&)
with
enum EPushBackError
{
ERROR_OUT_OF_MEMORY
};

Unfortunately, no such thing exists in C++ (nor in any other language
I know, not even Ada95).

Regards,
Stuart
 
J

Jorgen Grahn

Hi,

Sometimes I found it very convenient to use STL in my application.

But one thing I hate is that STL containers throw exceptions. Because
we handle errors explictly in our application, we don't want
exceptions.

Don't they just use exceptions for out-of-memory situations, just like
operator new? (Plus some special cases like std::vector<T>::at(),
which you don't have to use.)

So if you use operator new already, the containers really don't make
exceptions more of a problem.

Also note that for many applications, catching out-of-memory up in
main() and exiting is enough.
I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

With g++, the containers will be unusable with exceptions turned off
-- your code won't compile. Don't know about other compilers, but I
fail to see how they can avoid using exceptions.
Specifically, will the following operation throw exceptions? How to
handle it without the "try, catch" clause?

Huh? The bug there isn't something that will be reported as an
exception. It will just crash -- if you're lucky.

/Jorgen
 
G

Goran Pusic

STL does throw on bugs. If you do not have bugs then it does not
throw.

That's too simplified. It throws on failed allocations and of course,
it does not try to be smart with exceptions from assignment operators
or copy constructors for user types.

Goran.
 
Ö

Öö Tiib

That's too simplified. It throws on failed allocations and of course,
it does not try to be smart with exceptions from assignment operators
or copy constructors for user types.

Allocator may throw something and your types you use in container may
throw something. Can it be called that "container throws". I don't
think so. So ... maybe not everything what is left are bugs ... but i
do not remember anything. Refresh me.
 
W

wij

Solution to that conundrum is to wrap each and every operation with
STL into a try/catch and return error code equivalent to caught
exception (or whatever you use to signal errors) from catch.
In addition, user's type used in a container should not throw the
same
type as the container declares to throw, otherwise the catch handler
could be confused what is really 'caught'.
Furthermore, nearly all types thrown should be in a way distinct.
 
G

Goran Pusic

Allocator may throw something and your types you use in container may
throw something. Can it be called that "container throws". I don't
think so. So ... maybe not everything what is left are bugs ... but i
do not remember anything. Refresh me.

If I am not mistaken, STL code will indeed throw because of:

1. a bug
2. OOM

(I agree, it's unfair to say that STL threw if actually user code
threw).

So ultimately, one could say that STL only throws due to OOM. That's
enough for me :).

Goran.
 
P

peter koch

Hi,

Sometimes I found it very convenient to use STL in my application.

But one thing I hate is that STL containers throw exceptions. Because
we handle errors explictly in our application, we don't want
exceptions.

I want to know whether there's any possibility to turn exceptions off,
just like the "new(std::nothrow)" option.

Specifically, will the following operation throw exceptions? How to
handle it without the "try, catch" clause?

The default behaviour is to throw an exception when you are out of
memory.
Simply set a new_handler that aborts when it is out of memory. Out of
memory will not be an error that you want to test for in most types of
code anyway.

/Peter
 
G

Goran Pusic

I worked in a shop like that once. We wrote our own string, vector and
map classes that had the same interface as the STL classes (our string
class was cleaner though,) and any situation where the standard class
would have thrown an exception, our classes aborted.

You don't need to go that far though, just treat every situation where
an exception is thrown as a pre-condition violation.

That's quite alright, except that it's not really nice to abort on
bad_alloc in particular. That's almost always too harsh.

It's only OK if the whole program is one "do work" iteration, and even
then, it cost little to write one catch in main(), e.g.

int main()
{
try { return work(); }
catch(const exception& e) // perhaps bad_alloc, perhaps something
else.
{ return error_code_from_exception(); /*nothrow guarantee here*/ }
}

Goran.
 
Ö

Öö Tiib

If I am not mistaken, STL code will indeed throw because of:

1. a bug
2. OOM

(I agree, it's unfair to say that STL threw if actually user code
threw).

So ultimately, one could say that STL only throws due to OOM. That's
enough for me :).

And handling OOM may have catch(std::bad_alloc&) in main() and maybe
in bigger memory consuming operations. Memory of computer is full so
what is there to do in function that did std::vector::push_back() ?
Nothing. End of world disaster for it. It must watch from side how it
flies.
 
J

Juha Nieminen

Stuart Redmann said:
That would be quite nice.

Exactly how would that be "quite nice"? What do you suggest the containers
do in case of an error? Silently misbehave? Something else? What?

When you start thinking about how you would be able to detect any
possible errors with STL containers, you will find that exceptions are,
in fact, the *easiest* and most practical way of doing that. Any other
method you might think of (such as putting an error code somewhere which
you would have to check) would result in much more complicated code from
your part and, more importantly, would result in significantly more
error-prone code (because you *will* forget to check such error codes).

Of course a data container silently misbehaving in case of error would
be the worst possible solution. By far.
 
R

RB

Hi Goran, ( I am assuming you are the same Goran that used to help
me on ms.public.vc.mfc before ms shut down the server )
I have studied exceptions quite a bit since you and Joe patiently
helped me. Though still much a novice dummy overall, from what
I have learned on exceptions I agree with your post.
It would appear to me that either you would have catch and handle
or swallow with "a catch and do nothing" if you were confident that your
callers error handling code could rectify the violation effects.
OR else have the results in your face OR in your back down the road.
I have a question at this point (hopefully I am posting this before the
Belgium time zone sleeps) and that is "exception specifications".
I.e if I define a function as:
int MyFunc( int Arg1, DWORD Arg2) throw( ) {.........}
(which according to data read would in some cases denote this function
would not throw "any" exception)
Albeit I don't see how they could be a solution for the OP since he is
dealing with a library already coded, I still have mixed information as to how
reliable they actually are and even more so, I've read that some modern
version compilers ignore them.
Given the inherent underlying hardware interrupt and OS implementation
it would seem that if you deny "some" exception handlers from taking place,
your machine would either blue screen crash or take off on an endless loop.
While lesser infractions would let the function or application or machine limp
along until a corruption is exposed and causes a failure of related consequence.
What is your knowledge on this.
Further for your comment or correction a few current concepts of mine.
1. Any exceptions thought of "not needed to be caught" would have to
be coded (in a perfect program) so that the exception never happens.
And debuggers can help make this more of a conceivable reality.
2. But debuggers cannot prevent a user opening the wrong file or
wrong format, or a third party lib foo bars or any other scenario that is
out of the control of the end product programmer.
3. It would appear that exceptions are a reality that hardware and OS
engineers deemed necessary to promote their product as more stable.
Even with the most foo bar programmer (in many cases like myself) the
underlying hardware/OS partnership brings up the crash dialog that
basically says "Your App programmer FooBarred so let him know"
Without exceptions the user sits at his screen wondering "WTF ! my
computer just broke".
4. Any exception that should be caught is one that the "error handling code
was not able to control " OR the exception structure excels as a vehicle for
covering an expanded area of code that needs to unwind, destruct, delete
and or reset items that have traversed up until the exception occured.
Good talking to you (or getting corrected for my ignorance) again. RB
 
R

RB

I agree with you. Please (if you have time) comment on
my reply to Goran in other offset thread further down.
 
S

Stuart Redmann

Juha said:
Exactly how would that be "quite nice"? What do you suggest the containers
do in case of an error? Silently misbehave? Something else? What?

Something that comes close to what I described in the paragraph you
decided to snip (without marking that you've done so) almost
completely. If C++ could generated two versions of the same function,
one using exceptions and one using error codes, this may be a useful
feature. Personally I don't have a problem with exceptions, even
though I think that try-catch-statements can make code unreadable
(which is why I use my personal pre-processor macros to hide them).

All I have to say is that there are cases where the user of some
library (in this case STL) wants to check every single operation, and
sometimes he may only be interested whether a lot of operations
succeeded. In the first case he'd prefer error codes, in the second
case exceptions. But noone wants to write two versions of the same
function, so it would be nice if C++ could generate two versions of a
function from a single definition (like the #import'ed type libraries
under Visual Studio).

Regards,
Stuart
 
G

Goran Pusic

And handling OOM may have catch(std::bad_alloc&) in main() and maybe
in bigger memory consuming operations. Memory of computer is full so
what is there to do in function that did  std::vector::push_back() ?
Nothing. End of world disaster for it. It must watch from side how it
flies.

Well, no, not really. You see, it all depends on what program does. If
program is one iteration of some work, then OOM is indeed the end of
the world.

But if the program is almost anything else, it isn't. Because,
typically, what happens is that code embarks on some path, allocates,
calculates (rinse, repeat)... When done, it cleans up whatever is
auxiliary and keeps some form of result (even if it is some
modification of the global state. Now... If said code path ends
happily, there probably was a peak on resource usage somewhere in the
middle, and then, when going back some of these resources were freed
(any temporary resources). If code path steps on resource shortage, it
has to go up the stack (or better yet, I should say something like
"resource allocation chain") and free any resources it obtained in the
meantime.

In both cases (and especially in a failure case), once code path is
"unwound", there __are__ resources available. Whether it's then
interesting to start some new operation or not, what do I know. But I
know that e.g. a well-behaved editor-type program, if it can't do some
manipulation on my document because of resource shortage, should not
just die in the middle of that operation. It should, instead, rewind,
and say "whoops, can't do that" and let me save what I have up to
now :). Similar goes to a lot of other program types (e.g. a server-
type app: - request comes in, but there's no resources to fulfill
that particulars request - so drop a bomb on that request and clean
up, but continue serving other clients). It's only straight-line code
that benefits ( a little :) ) from immediate death on resource
shortage.

Goran.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top