Topic: Exceptions and the Standard C Library
Author: kanze@us-es.sel.de (James Kanze)
Date: 4 May 93 18:24:56 Raw View
In article <1993May2.154918.1940@taumet.com> steve@taumet.com (Steve
Clamage) writes:
|> This issue [does new throw an exception] is not entirely settled, but
|> what seems likely to be adopted is this:
|> "operator new" will be defined to throw an exception under specified
|> circumstances. Precisely because this would break existing C++
|> programs, a vendor might supply the option of preserving the old
|> behavior (return zero) or getting the new behavior (throw an exception).
|> The C++ implementor could provide the choice by means of different
|> pre-defined new-handlers. (Saying the vendor might choose to provide
|> these options is like saying the vendor might choose to stay in business.)
Does this mean that the standard would no longer mandate the presence
of a user settable new handler? My understanding was that the default
handler would throw an exception, but that the rest of the mechanism
would remain basically unchanged. (Admittedly, this is the result of
a quick scan of the discussions. As the main point of my committee
activity is core issues, I have not looked into this deeply.)
|> The Standard would be silent on this issue, but the whole area would be
|> carefully worded so as to make this possible. This is similar to the
|> situation with C compilers which allow code which violates the C
|> Standard, but which have options to enforce the Standard strictly.
--
James Kanze email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: steve@taumet.com (Steve Clamage)
Date: Sun, 2 May 1993 15:49:18 GMT Raw View
maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>>>The library group of the committee is considering whether to
>>>'C++' ise the 'C' library.
> Woops, sorry: I did not mean to imply that the only
>or best way to do this was to modify the C library. It would
>be possible, for example, to provide a C++ maths library
>distinct from the C one. ...
The library group and the entire C++ Committee considered whether to
modify the C library, and decided (in principle) in 1990 or 1991
not to do so. The idea was to import the C library largely unchanged
in specification, so that a C program which otherwise conformed to C++
rules would continue to work in the same way when compiled as C++.
(And precompiled C functions which depended on Standard C library
behavior could still be linked to C++ programs.)
After CONSIDERABLE study and work, a few areas of the C Library were
identified as being incompatible with C++, and the specifications of
these were modified accordingly. For example, some string functions
return a non-const pointer to a const string which was passed in. This
violates type safety, so we specified two overloaded versions of the
function. Some C library features can lead to undefined behavior in
C++ ("offsetof" a member in a virtual base class, for example), and
we modified the description of these accordingly.
For the rest, we decided to leave the C library alone. We have so far
not seriously contemplated C++ replacements for any of the C library
functions. We have decided to add some C++ class libraries which happen
to address some of the areas also addressed by the C library, such as
iostream and string classes.
>>> IMHO it is bad enough that the C++ 'new' throws
>>>an exception, a decision that probably breaks a lot of
>>>code .. but only C++ code, not C code.
>>>
>>Could you elaborate on this statement? Does this mean that the
>>set_new_handler approach is gone? Or that the default new_handler
>>throws the exception (and so you could choose to override the
>>behavior)?
> I dont have the exact details. I'm trying to obtain them.
>Anyone else reading here who does: I'd like to know too.
This issue is not entirely settled, but what seems likely to be adopted
is this:
"operator new" will be defined to throw an exception under specified
circumstances. Precisely because this would break existing C++
programs, a vendor might supply the option of preserving the old
behavior (return zero) or getting the new behavior (throw an exception).
The C++ implementor could provide the choice by means of different
pre-defined new-handlers. (Saying the vendor might choose to provide
these options is like saying the vendor might choose to stay in business.)
The Standard would be silent on this issue, but the whole area would be
carefully worded so as to make this possible. This is similar to the
situation with C compilers which allow code which violates the C
Standard, but which have options to enforce the Standard strictly.
--
Steve Clamage, TauMetric Corp, steve@taumet.com
Author: steve@taumet.com (Steve Clamage)
Date: Sat, 24 Apr 1993 17:07:50 GMT Raw View
krc@wam.umd.edu (Kevin R. Coombes) writes:
>One example commonly used to illustrate why (and where) you might want
>to use exceptions is in doing mathematical computations. ...
>In a practical sense, I do not see how this goal can be acheived. Here
>I am working under the assumption that (since the ANSI/ISO C standard
>is a base document for the C++ standardization effort) the use of
>exceptions must be compatible with the existing C library.
For the moment, I would say you are out of luck. The C Standard
forbids the math functions to raise signals. The C++ Standard
(so far) has imported that section of the C Standard unchanged.
The next version of the C Standard may have a better approach to
handling math errors (as you note, errno is useless), in which case
it would be adopted into C++ (at some point).
The C++ Committee doesn't want to invent any solutions to problems
with the math library, since there is currently a standards effort
in that area: X3J11.1, NCEG. The C++ Standard will (presumably) adopt
whatever is adopted for C. The C++ Committee is also providing input
to the C Committee to ensure that the results are also suitable for C++.
--
Steve Clamage, TauMetric Corp, steve@taumet.com
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sun, 25 Apr 1993 18:53:08 GMT Raw View
In article <1993Apr23.143828.15223@wam.umd.edu> krc@wam.umd.edu (Kevin R. Coombes) writes:
>One example commonly used to illustrate why (and where) you might want
>to use exceptions is in doing mathematical computations. (Stroustrup's
>books use this example.) For example, you might have a base class
>MathError, with derived classes like ZeroDivide, Overflow, Underflow,
>PrecisionLoss, Domain, Range, etc., that you can throw whenever bad
>things happen. The benefit you are supposed to gain is that
>error handling code is not scattered throughout the code, but can be
>concentrated.
>
>In a practical sense, I do not see how this goal can be acheived. Here
>I am working under the assumption that (since the ANSI/ISO C standard
>is a base document for the C++ standardization effort) the use of
>exceptions must be compatible with the existing C library. Suppose,
>for example, I want to use the functions in <math.h>, but generate
>execptions when errors occur. The only portable way that I can see to do
>this is to test errno after every call to a <math.h> function; if it has
>been set, then I throw the exception. Doesn't this approach defeat the
>purpose? After all, I still have to remember to check errno every time,
>so the error handling code is still spread around the program. Did I miss
>something?
Yes. You are assuming that 'math.h' will be a C library.
The library group of the committee is considering whether to
'C++' ise the 'C' library.
It may be an alternate C++ library is provided,
and it may be that a C++ library is provided with extern "C"
interface (but a C++ library all the same).
In any case it is easy to so this:
double Sin(double x) {
double y = sin(x);
if(errno)throw Matherr(errno);
return y;
}
and call Sin instead of sin. You existing code using 'sin'
already checks for 'errno' and so 'sin' probably should not
throw an exception.
>
>(All of the compilers I actually use tell me that the math library calls
>a function called matherr() when these errors occur. On those systems,
>I could write my own version to throw the exception, and avoid the
>checks for errno. But matherr() did not make it into the ANSI C
>Standard. Will some equivalent get added to the C++ Standard to allow
>me to generate exceptions portably and conveniently? If so, what does
>it mean to say that the C standard is a base document?)
It means its a starting point for generating the working
papers for eventual creation of the Draft C++ Standard.
No part of C actually has to be preserved:
"As close to C as possible and no closer" (Stroustrup)
>
>I can see one way to get around this, but it involves changing all my
>code. Write functions like
>
>double my_log(double r)
>{
> double retval = log(r);
> if (errno) {
> // clear errno, and throw an exception.
> }
> return retval;
>}
>
>But then I have to use my_log instead of log everywhere. Is there any
>way to avoid this problem?
It isnt a problem. It is probably exactly what you want.
The you can chose. Then your old code continues to work.
It would be *much* more of a problem if any C library
function threw an exception where previously it returned with
an error indication.
IMHO it is bad enough that the C++ 'new' throws
an exception, a decision that probably breaks a lot of
code .. but only C++ code, not C code.
malloc had better NOT throw an exception!
However consider this one:
float x = 0.0;
float y = 1/x;
Now if *that* throws an exception we're in trouble: you cant
provide a convenient wrapper for this. (You can if you
make a class Float though, or you live with:
divide(1,x); // <grin>
The correct way to do this, IMHO is to use NaNs. These
propagate up to the point where you do the test,
if they are silent NaNs.
However, if an exception is generated, you'll just have to
trap such code somewhere.
Perhaps the correct approach is to have a
'set_dividebyzero_handler'
function so that the default just throws an exception,
but you can turn this behaviour off and retry.
>
>I also see a similar problem if the exceptions occur during raw arithmetic
>on floating point numbers, not in the math library. In this case, the
>system is going to generate an asynchronous SIGFPE and call a signal
>handler.
Exceptions do not handle asynchronous faults.
My PC does not generate SIGFPE's whatever they are :-)
Optionally, it can cause a hardware interrupt.
Whatever the behaviour of say divide is supposed to be
will have to implemented directly by the compiler: such
implementation is transparent and doesnt have to be portable.
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: krc@wam.umd.edu (Kevin R. Coombes)
Date: Mon, 26 Apr 1993 16:40:54 GMT Raw View
In article <1993Apr25.185308.6709@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>In article <1993Apr23.143828.15223@wam.umd.edu> krc@wam.umd.edu (Kevin R. Coombes) writes:
>>One example commonly used to illustrate why (and where) you might want
>>to use exceptions is in doing mathematical computations.
>>
>>In a practical sense, I do not see how this goal can be acheived. Here
>>I am working under the assumption that (since the ANSI/ISO C standard
>>is a base document for the C++ standardization effort) the use of
>>exceptions must be compatible with the existing C library.
>
> Yes. You are assuming that 'math.h' will be a C library.
I thought I already said that....
>The library group of the committee is considering whether to
>'C++' ise the 'C' library.
>
Before Jim Adcock says it: it's ridiculous to do that. If you are using
the ANSI/ISO standard as a base document, then there is no excuse for
changing that document capriciously. One of the factors that still
drives the growth of C++ is C compatibility. The C standard describes
the behaviors of the functions prototyped in <math.h>. If the C++
committee wants to change that behavior in a radical way, then they
are free to define a new header <math.hh> that describes the functions
with the new behavior. It might even use the same names for the
functions (but they'd be mangled by the compiler and thus linked
properly).
> No part of C actually has to be preserved:
>"As close to C as possible and no closer" (Stroustrup)
>> [...stuff omitted...]
>
> It would be *much* more of a problem if any C library
>function threw an exception where previously it returned with
>an error indication.
>
> IMHO it is bad enough that the C++ 'new' throws
>an exception, a decision that probably breaks a lot of
>code .. but only C++ code, not C code.
>
Could you elaborate on this statement? Does this mean that the
set_new_handler approach is gone? Or that the default new_handler
throws the exception (and so you could choose to override the
behavior)?
>
> However consider this one:
>
> float x = 0.0;
> float y = 1/x;
>
>The correct way to [handle] this, IMHO is to use NaNs. These
>propagate up to the point where you do the test,
>if they are silent NaNs.
>
>However, if an exception is generated, you'll just have to
>trap such code somewhere.
>
>Perhaps the correct approach is to have a
>
> 'set_dividebyzero_handler'
>
>function so that the default just throws an exception,
>but you can turn this behaviour off and retry.
>
But that already exists in C; you write your
void divide_by_zero_handler() { /* do something */ }
and install it with
signal(SIGFPE, divide_by_zero_handler);
>
>>
>>I also see a similar problem if the exceptions occur during raw arithmetic
>>on floating point numbers, not in the math library. In this case, the
>>system is going to generate an asynchronous SIGFPE and call a signal
>>handler.
>
> Exceptions do not handle asynchronous faults.
>
> My PC does not generate SIGFPE's whatever they are :-)
>
> Optionally, it can cause a hardware interrupt.
Mine does... Borland and Microsoft both convert the hardware interrupt
into a call to the SIGFPE handler installed by the call to signal.
g++ does similar things on UNIX. Both signal and SIGFPE are part of
the C standard. There's just no portable way to convert that signal
into an exception to be processed by C++ code.
Kevin Coombes <krc@math.umd.edu>
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Thu, 29 Apr 1993 10:52:00 GMT Raw View
In article <1993Apr26.164054.7887@wam.umd.edu> krc@wam.umd.edu (Kevin R. Coombes) writes:
>In article <1993Apr25.185308.6709@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>
>>The library group of the committee is considering whether to
>>'C++' ise the 'C' library.
>>
>Before Jim Adcock says it: it's ridiculous to do that. If you are using
>the ANSI/ISO standard as a base document, then there is no excuse for
>changing that document capriciously.
Woops, sorry: I did not mean to imply that the only
or best way to do this was to modify the C library. It would
be possible, for example, to provide a C++ maths library
distinct from the C one. There would be some
advantage perhaps in having C++ functions:
Sin(float);
Sin(double);
Sin(complex);
>One of the factors that still
>drives the growth of C++ is C compatibility. The C standard describes
>the behaviors of the functions prototyped in <math.h>. If the C++
>committee wants to change that behavior in a radical way, then they
>are free to define a new header <math.hh> that describes the functions
>with the new behavior. It might even use the same names for the
>functions (but they'd be mangled by the compiler and thus linked
>properly).
I dont think it really can use the same names: that would
make the libraries incompatible.
>> It would be *much* more of a problem if any C library
>>function threw an exception where previously it returned with
>>an error indication.
>>
>> IMHO it is bad enough that the C++ 'new' throws
>>an exception, a decision that probably breaks a lot of
>>code .. but only C++ code, not C code.
>>
>Could you elaborate on this statement? Does this mean that the
>set_new_handler approach is gone? Or that the default new_handler
>throws the exception (and so you could choose to override the
>behavior)?
I dont have the exact details. I'm trying to obtain them.
Anyone else reading here who does: I'd like to know too.
But, as I understand it you can disable exception
throwing by set_new_handler(0). I guess that it must therefore
be the 'new handler' that actually throws the exception.
In any case, while I'm certain that you will be
able to disable keyword new throwing an exception, the problem
I refer to is what to do if you want to 'upgrade' your code
to support allocation exceptions.
You might *have* to do that to use a new version of
a library that expects allocation exceptions to be thrown.
In that case, much of the code in your program related to
allocation will have to be rewritten -- as far as I can see,
and assuming you dont want to abort when memory runs out.
>> My PC does not generate SIGFPE's whatever they are :-)
>
>Mine does... Borland and Microsoft both convert the hardware interrupt
>into a call to the SIGFPE handler installed by the call to signal.
I apologise to my compiler.
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: krc@wam.umd.edu (Kevin R. Coombes)
Date: Fri, 23 Apr 1993 14:38:28 GMT Raw View
One example commonly used to illustrate why (and where) you might want
to use exceptions is in doing mathematical computations. (Stroustrup's
books use this example.) For example, you might have a base class
MathError, with derived classes like ZeroDivide, Overflow, Underflow,
PrecisionLoss, Domain, Range, etc., that you can throw whenever bad
things happen. The benefit you are supposed to gain is that
error handling code is not scattered throughout the code, but can be
concentrated.
In a practical sense, I do not see how this goal can be acheived. Here
I am working under the assumption that (since the ANSI/ISO C standard
is a base document for the C++ standardization effort) the use of
exceptions must be compatible with the existing C library. Suppose,
for example, I want to use the functions in <math.h>, but generate
execptions when errors occur. The only portable way that I can see to do
this is to test errno after every call to a <math.h> function; if it has
been set, then I throw the exception. Doesn't this approach defeat the
purpose? After all, I still have to remember to check errno every time,
so the error handling code is still spread around the program. Did I miss
something?
(All of the compilers I actually use tell me that the math library calls
a function called matherr() when these errors occur. On those systems,
I could write my own version to throw the exception, and avoid the
checks for errno. But matherr() did not make it into the ANSI C
Standard. Will some equivalent get added to the C++ Standard to allow
me to generate exceptions portably and conveniently? If so, what does
it mean to say that the C standard is a base document?)
I can see one way to get around this, but it involves changing all my
code. Write functions like
double my_log(double r)
{
double retval = log(r);
if (errno) {
// clear errno, and throw an exception.
}
return retval;
}
But then I have to use my_log instead of log everywhere. Is there any
way to avoid this problem?
I also see a similar problem if the exceptions occur during raw arithmetic
on floating point numbers, not in the math library. In this case, the
system is going to generate an asynchronous SIGFPE and call a signal
handler. The only portable thing this signal handler can do is (i) call
signal to re-establish itself, or (ii) assign a value to a variable of
type "volatile sig_atomic_t". (Again, all the compilers I use allow me
to reset the flaoting point subsystem and longjmp to a preestablished
handler. But that behavior is not required by the standard.) Basically,
I must set my own errno and check it after the operation completes.
The error handling code is again scattered around. Is there any method in
the working documents for the C++ standard to allow SIGFPE's to be
converted into exceptions?
Kevin Coombes <krc@math.umd.edu>