Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do exceptions work ?

2 views
Skip to first unread message

Ian Main

unread,
Apr 27, 1997, 3:00:00 AM4/27/97
to

I've just read in Herbert Schildts - C++, The Complete Reference (2nd
Ed) that a try block 'mointors' the instruction within the block for an
exception of a given type.

QUESTION:-
How can the compiler create code that monitors only a section of a
program for an exception to occur ? (I mean what is the mechanism behind
try/catch/throw).

I'm a digital designer (boo hiss you say!) trying to learn C++ purely
for my own interrest. I assume that the term 'exception' used in C++
books refers to the same type of 'exceptions' that occurs in a
microproprocessor ie. divide by zero, bus error, hardware interrupt
request etc.

I have an answer to my own question (but is a PURE GUESS and only how I
IMAGINE the try block could work).

ANSWER (?? - comments please) :-

When an exception is thrown using the throw statement (eg throw 100;)
the processor actually executes an assembler instruction called a
software interrupt (SWI). Just before the SWI is executed, the value 100
(in this example) is stored (along with the type int) somewhere that the
SWI interrupt service routine (SWI ISR) can 'see' it (on the stack?).
When the SWI ISR executes, the type of the thrown exception in retrieved
and a kind of switch(type) performed ie.

SWI_ISR()
{
switch (type) {

case int: // assuming the program defined a 'catch (int)'
execute catch int code here........
break; // (oooops novice nearly forgot these !!)

case char: // assuming 'catch(char)' was defined
execute catch char code here.......
break;

default: // assuming 'catch(..) was defined
execute catch(...) code here.......
}
}

To allow the try block to monitor only a section of code (within the try
block) the SWI interrupt vector is altered at the start of the try block
to point to the correct ISR and then restored to its original vlaue at
the end.

try { // alter SWI interrupt vector to point a new SWI ISR
// defined by associated catch statements

blah; // code being monitored

} // alter SWI interrupt vector to point back to
// original SWI ISR

--
Ian Main - Chiz Design Services Ltd.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]


Gerhard Huebner

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

Ian Main wrote:

> I'm a digital designer (boo hiss you say!) trying to learn C++
> purely
> for my own interrest. I assume that the term 'exception' used in C++
>
> books refers to the same type of 'exceptions' that occurs in a
> microproprocessor ie. divide by zero, bus error, hardware interrupt
> request etc.

Absolutely not! C++ exceptions havent' got ANYTHING in common with CPU
exceptions. C++ exceptions are a powerful tool to handle errrors that
could normally only be handled by returning error codes from the
function that failed to execute. In case of large call graphs, this
would result in quite a lot of combinations of error scenarios which
would be extremely difficult to handle.

On the other hand, C++ exceptions permit you to handle error conditions
independently from the call graph. You can throw exceptions wherever you
want and catch them wherever you want. C++ exceptions are used to handle
errors like

- no memory in case of dynamic allocation
- file could not be opened
- pre/postcondition violated
- any other software condition that cannot be handled properly

C++ Exceptions are not raised by the CPU but thrown by the program
segment that encountered an unsolvable problem. It is up to the
programmer to determine which exception to throw and where to catch it.

--
Dipl.-Phys. Gerhard Huebner __
Institute of Astronautics \ \____ "Not a plucky hero
--------------------------------===>--____> until one reaches
Technical University of Munich /_/ the Great Wall"
Tel.: +49-89-289-16015, Fax: 16004

Paul D. DeRocco

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

Ian Main wrote:
>
> I've just read in Herbert Schildts - C++, The Complete Reference (2nd
> Ed) that a try block 'mointors' the instruction within the block for an
> exception of a given type.
>
> QUESTION:-
> How can the compiler create code that monitors only a section of a
> program for an exception to occur ? (I mean what is the mechanism behind
> try/catch/throw).

Actually, it involves cooperation between the thrower and catcher, just
as subroutine linkage involves cooperation between the caller and the
callee.

The precise mechanism can be extremely complicated, but the x86
processor implementations that I've seen work like this. Basically any
function that has a catch block sets up a data structure on the stack
called an exception context, which includes, among other things, a
pointer to the previous execption context (analogous to the way each
function's stack frame contains a pointer to the calling function's
stack frame). Somewhere in some global (or thread-global) variable is a
pointer to the most recently entered exception context. The exception
context also contains a pointer to some static data structure that
includes information about what types are to be caught (represented
perhaps by type_info objects), and where the exception handling code is
for each type.

When an exception is thrown, a helper function in the library is called,
with a pointer to the object being thrown and a pointer to the type_info
(or other similar) object representing the type. The helper function
follows the chain of exception contexts on the stack, and does a
comparison at each level to see if it has found a matching exception
handler. When it finds one, it cuts the stack back and jumps to that
handler's code, with the thrown object as a "parameter". The comparison
isn't for simple equality, as it has to handle the case of a derived
class object being caught by a base class, so it gets pretty hairy.
What's more, if the object is caught by value, instead of by reference,
the object has to be copied, which may involve a call to the copy
constructor; if there is one, there will be some means of finding it
through the type_info object.

What's more, even functions that don't have try/catch blocks are
involved in exception handling. If an object of a class that has a
destructor is created as a local variable, the function that contains it
also has to splice into the exception context chain. However, it isn't
supplying exception handlers, just code to call destructors. As the
stack is unwound during an exception throw, this code is invoked, thus
calling the appropriate destructors for these local objects. If there
are multiple such objects within a function, or arrays of them, perhaps
at different block nesting levels, this also gets hairy, because a fair
amount of bookkeeping is involved in keeping track of which objects have
been constructed and which have not.

Other implementations do it somewhat differently, following the chain of
regular stack frames set up by all functions, instead of following a
separate chain of exception contexts. The entering and leaving of
try/catch blocks, as well as the creation and destruction of local
objects with destructors, effectively partitions the code into regions
that require different treatment, so the boundaries of these regions are
placed into a static table, along with pointers to the code required to
clean up if an exception occurs during each region. During stack
unwinding, then, the return address at each level tells what code was
executing at the time of the function call, and the system does a table
search on that address to figure out what cleanup code needs to be
executed. This has the advantage of zero overhead when exceptions are
not thrown, but considerable overhead when they are.

If you have access to a C++ compiler, and you're interested in delving
into this, find the compiler switch for producing assembly language
output, and see what it generates.

--

Ciao,
Paul

(Please send e-mail to mailto:pder...@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)

David Vandevoorde

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

Ian Main wrote:
[...]

> QUESTION:-
> How can the compiler create code that monitors only a section of a
> program for an exception to occur ? (I mean what is the mechanism
> behind try/catch/throw).
[...]

There are many alternatives for this problem, and certainly
all vendors differ in the details of their implementations.
However, most modern implementations are built long the
same principles.

First, the compiler assembles so-called `range-tables': these
are tables associating with various portions of your code,
actions that should occur were an exception to cause unwinding
of the system stack record associated with that code. Typical
actions include the invocation of destructors for automatic
objects (or arrays thereof) and the terminating of the unwind
operation by invoking a catch-clause.

E.g.:

try {
YourClass a;
f();
} catch (X const& x) {
// ...
} catch (Y& x) {
// ...
}

For the above code, the compiler will notice that exceptions
might be thrown within the try-block:
1) because the default-construction of `a' failed:
the range-table entry associated the code-sequence
that invokes this constructor will not include any
cleanup action,
2) because the call to f() terminated through an exception:
the range-table entry will include an action to clean up
`a'.
Furthermore, each of these entries will include a lookup
operation through the handlers available for this try-block.
For this to be possible, this action will include information
for every caught type (as I said above, there are a myriad
possibilities for the details of this; some compilers extend
the mechanisms that support the typeid-operator for this
purpose). Had there not been a try-block, there might not have
been such a lookup-action (I say `might' because throw-
specifications are sometimes implemented in a very similar
way).

A throw-expression is then usually translated into an internal
function that walks the system stack, looking up each activation
record in the range table and performing the associated actions
until a matching catch clause has been found. Hence, this stack-
walking function is passed information concerning the thrown type.

Some implementations perform this walk-back in two stages: the
first stage does not perform any cleanup actions but only
looks for a matching catch clause while leaving the stack intact.
This permits a debugger to examine the stack at the catch-point.
The second stage then performs the cleanup. The disadvantage
compared to merging the two stages is the increased cost of a
throw-operation (which in general is costly anyhow).

Finally, note that the range tables increase the size of your
executable, but need not be loaded until an actual exception
is thrown. I.e., under non-exceptional circumstances, the foot-
print of your application should remain relatively unaffected.

Daveed

Robert Mashlan

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

Ian Main <i...@chiz-design-ltd.demon.co.uk> wrote:

>QUESTION:-
>How can the compiler create code that monitors only a section of a
>program for an exception to occur ? (I mean what is the mechanism behind
>try/catch/throw).
>

>I'm a digital designer (boo hiss you say!) trying to learn C++ purely
>for my own interrest. I assume that the term 'exception' used in C++
>books refers to the same type of 'exceptions' that occurs in a
>microproprocessor ie. divide by zero, bus error, hardware interrupt
>request etc.

These are not the same as C++ exceptions. A C++ exception cannot
happen asynchronously, it's caused by deliberate action on the part of
the C++ code.

C++ are typically implemented by using a linked list of node
structures on the stack. A global variable (or a per-thread variable
in multi-threaded environments) points to the head of this linked
list. Whenever you enter a try block, a node is created and
initialized on the stack, like a local variable. The global head
pointer is updated whenever you enter and leave a try block.

When a C++ exception is thrown, the runtime library will walk this
linked list of nodes to find the catch handler. This is typically
done by calling a function through a pointer stored in the node which
returns true/false given the some information describing the type of
the thrown object.

Once the handler is found, it walks the linked list again, calling
another function through a pointer that executes the cleanup code for
each try block, down to the catch handler. The head pointer would
then be updated to point to the node for the try block which encloses
the catch handler and the catch handler is executed. If the catch
handler rethrows or throws another exception, the process starts over.

---
Robert Mashlan R2M Software rmas...@r2m.com
Internet Resources for Windows Developers http://www.r2m.com/windev/

Chris Perrott

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

Gerhard Huebner wrote:

>
> Ian Main wrote:
>
> > I'm a digital designer (boo hiss you say!) trying to learn C++
> > purely
> > for my own interrest. I assume that the term 'exception' used in C++
> >
> > books refers to the same type of 'exceptions' that occurs in a
> > microproprocessor ie. divide by zero, bus error, hardware interrupt
> > request etc.
>
> Absolutely not! C++ exceptions havent' got ANYTHING in common with CPU
> exceptions.

This is very strange. I see C++ exceptions as an abstraction of the CPU
exceptions, and just recently I stated this in some course notes I've
been preparing. I note that overflow_exception and underflow_exception
are standard. My understanding is that catch(...) will indeed catch
CPU-generated exceptions.

[Underflow and overflow result in undefined behavior, so if an
implementation turns them into C++ exceptions, it is perfectly
within bounds. The exception handling mechanism used on most
systems, however, does not handle asynchronous exceptions correctly,
and in general, there is no relationship whatsoever between C++
exceptions CPU exceptions. -- jak ]

--
Chris Perrott

James Kanze

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

rmas...@r2m.com (Robert Mashlan) writes:

|> Ian Main <i...@chiz-design-ltd.demon.co.uk> wrote:
|>
|> >QUESTION:-
|> >How can the compiler create code that monitors only a section of a
|> >program for an exception to occur ? (I mean what is the mechanism behind
|> >try/catch/throw).
|> >

|> >I'm a digital designer (boo hiss you say!) trying to learn C++ purely
|> >for my own interrest. I assume that the term 'exception' used in C++
|> >books refers to the same type of 'exceptions' that occurs in a
|> >microproprocessor ie. divide by zero, bus error, hardware interrupt
|> >request etc.
|>

|> These are not the same as C++ exceptions. A C++ exception cannot
|> happen asynchronously, it's caused by deliberate action on the part of
|> the C++ code.

Yes and no. A compiler is free to convert undefined behavior (e.g.:
divide by zero) into an exception if it pleases. (An implementation is
free to do anything it wants in the face of undefined behavior.) This
is not part of the C++ language, however. If a compiler does do this,
it should be considered an extension.

--
James Kanze home: ka...@gabi-soft.fr +33 (0)1 39 55 85 62
office: ka...@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --

James Kanze

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

Ian Main <i...@chiz-design-ltd.demon.co.uk> writes:

|> I've just read in Herbert Schildts - C++, The Complete Reference (2nd
|> Ed) that a try block 'mointors' the instruction within the block for an
|> exception of a given type.

This sounds like very poor wording, to put it mildly. Given the quality
of Schildt's writing on C, I'd be very sceptical of anything he says
about any language. (His "Annotated C Standard" is generally cited as
the summum of all of the errors one can possibly make concerning C.)

|> QUESTION:-
|> How can the compiler create code that monitors only a section of a
|> program for an exception to occur ? (I mean what is the mechanism behind
|> try/catch/throw).

As I said, monitors is a poor choice of words. The try block simply
defines a point to return to in case of throw.

|> I'm a digital designer (boo hiss you say!) trying to learn C++ purely
|> for my own interrest. I assume that the term 'exception' used in C++
|> books refers to the same type of 'exceptions' that occurs in a
|> microproprocessor ie. divide by zero, bus error, hardware interrupt
|> request etc.

Not at all. An exception in C++ has nothing to do with hardware. An
exception is raised by a throw expression.

Things like divide by zero result in undefined behavior in C++; an
implementation could map them to a C++ exception. (It could also
reformat the hard disk when they occur, and still be conforming. From a
quality of implementation point of view, of course, the exception is
preferrable.) Most implementations I'm familiar with don't, but simply
core dump the process instead.

Note that one important aspect of C++ exceptions is that they are
synchronous. They only occur when the compiler knows they can occur,
and not at any arbitrary moment.

|> I have an answer to my own question (but is a PURE GUESS and only how I
|> IMAGINE the try block could work).
|>
|> ANSWER (?? - comments please) :-
|>
|> When an exception is thrown using the throw statement (eg throw 100;)
|> the processor actually executes an assembler instruction called a
|> software interrupt (SWI).

Not at all. On most machines, trying to execute a software interrupt
will cause the OS to abort the process. Typically, the compiler
generates tables containing return addresses and things to do to clean
up at that address. A throw expression causes a copy of the thrown
object to be constructed in pseudo-static memory (in fact, a private
heap or stack), and then walks back up the stack. For each return
address, it looks up in the table, and executes whatever cleanup is
there. Return addresses in a try block also have a list of catch types
and their addresses associated. If the thrown type matches one of the
catch types, the stack walk back terminates, and the function "returns"
to the catch clause.

Gerhard Huebner

unread,
Apr 30, 1997, 3:00:00 AM4/30/97
to

Chris Perrott wrote:

> This is very strange. I see C++ exceptions as an abstraction of the
> CPU
> exceptions, and just recently I stated this in some course notes
> I've
> been preparing. I note that overflow_exception and
> underflow_exception
> are standard. My understanding is that catch(...) will indeed catch
> CPU-generated exceptions.

C++ exceptions are just another way of controlling program execution
like "if-else" or "case" statements although experts agree that
exceptions should NOT be used for regular control but only for
situations which cannot be handled properly the conventional way. It is
not possible to "convert" CPU exceptions into C++ exceptions because an
exception is thrown with a "throw" statement in the C++ source code,
whereas a CPU exception can be raised anywhere and anytime. The C++
exception must be thrown from somewhere within the call graph because
the exception handlers that "catch" the exception must be on a higher
level in the call graph hierarchy than the "throw" statements in order
to be able to intercept them.

However, you can introduce user-defined data types that check numerical
errors like overflow, division by zero etc. and you can let their member
functions throw exceptions. This may be quite an elegant way to deal
with numerical errors because you replace the "plain crash" with a
"controlled crash".

> and in general, there is no relationship whatsoever between
> C++
> exceptions CPU exceptions. -- jak ]

Exactly.

--
Dipl.-Phys. Gerhard Huebner __
Institute of Astronautics \ \____ "Not a plucky hero
--------------------------------===>--____> until one reaches
Technical University of Munich /_/ the Great Wall"
Tel.: +49-89-289-16015, Fax: 16004

Chris Perrott

unread,
May 2, 1997, 3:00:00 AM5/2/97
to

Gerhard Huebner wrote:
>
> Chris Perrott wrote:
>
> > This is very strange. I see C++ exceptions as an abstraction of the
> > CPU exceptions,

> It is


> not possible to "convert" CPU exceptions into C++ exceptions because an
> exception is thrown with a "throw" statement in the C++ source code,
> whereas a CPU exception can be raised anywhere and anytime. The C++
> exception must be thrown from somewhere within the call graph because
> the exception handlers that "catch" the exception must be on a higher
> level in the call graph hierarchy than the "throw" statements in order
> to be able to intercept them.

A CPU exception cannot be raised "anywhere and any time". Except in
pathological cases, a floating point exception can be raised only by
the execution of a floating point instruction, and such an instruction
does have its position in the call graph. Practically all CPUs support
hardware exceptions that generate an interrupt, causing an interrupt
handler to be invoked in a manner very similar to a subroutine call.
There is no reason why an interrupt handler cannot produce a C++
exception.

It would be nice if someone other than Gerhard would comment on this...


>
> > and in general, there is no relationship whatsoever between
> > C++
> > exceptions CPU exceptions. -- jak ]
>
> Exactly.
>

--
Chris Perrott

Bernard Badger

unread,
May 3, 1997, 3:00:00 AM5/3/97
to

In article <5kc8ur$f...@netlab.cs.rpi.edu> Chris Perrott
<cper...@pacific.net.sg> writes:

I agree that hardware exceptions can be mapped into the software
exception mechanism. I believe that Ada has this capability. I
cannot judge whether converting hardware exceptions is even allowed by
the standard. I'm only saying that the concept is plausible, and has
precedence in other languages. It does have its problems, because
it's hard to guarantee that recovery code won't raise more exceptions.

It would be nice if someone other than Gerhard would comment on
this...
>
> > and in general, there is no relationship whatsoever
between
> > C++
> > exceptions CPU exceptions. -- jak ]
>
> Exactly.
>

I think that this turns somewhat on the ambiguous phrase "in general".
I believe that it is being used here in the sense of,
"there is no pre-defined relationship between exceptions and CPU
exceptions
which is required in all cases."
This is in contrast to the possible meaning, "in most cases, CPU
exceptions
aren't mapped into C++ exceptions."

Even if CPU exceptions exist, it is no doubt highly implementation
dependent
how they may be mapped into the exception handling mechanism.

--
Bernard A. Badger bba...@mail.ccur.com
11. Thou shalt not Spam!

Paul D. DeRocco

unread,
May 3, 1997, 3:00:00 AM5/3/97
to

Chris Perrott wrote:

>
> Gerhard Huebner wrote:
> >
> > It is
> > not possible to "convert" CPU exceptions into C++ exceptions because an
> > exception is thrown with a "throw" statement in the C++ source code,
> > whereas a CPU exception can be raised anywhere and anytime. The C++
> > exception must be thrown from somewhere within the call graph because
> > the exception handlers that "catch" the exception must be on a higher
> > level in the call graph hierarchy than the "throw" statements in order
> > to be able to intercept them.
>
> A CPU exception cannot be raised "anywhere and any time". Except in
> pathological cases, a floating point exception can be raised only by
> the execution of a floating point instruction, and such an instruction
> does have its position in the call graph. Practically all CPUs support
> hardware exceptions that generate an interrupt, causing an interrupt
> handler to be invoked in a manner very similar to a subroutine call.
> There is no reason why an interrupt handler cannot produce a C++
> exception.

Under 32-bit DPMI, I've successfully installed handlers for general
protection faults and unknown page faults that turn these into C++
exceptions. I throw an error message that says something like

Internal error at 0197:00411926

which winds up being caught at the top level of the program and
displayed to the user. That way, instead of the program simply dying, or
reporting an information-free message, it gives the user a piece of data
which often helps me find the bug.

This, however, makes it almost impossible to use exception
specifications anywhere, since protection faults can happen any time you
give any function a null, dangling or uninitialized pointer, or even an
out-of-range index. With exception specifications, all these unexpected
exceptions would in fact call unexpected(), and wind up aborting the
program. For this reason, I don't like exception specifications, and
prefer not to use them at all.

--

Ciao,
Paul

(Please send e-mail to mailto:pder...@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Bradd W. Szonye

unread,
May 4, 1997, 3:00:00 AM5/4/97
to

Chris Perrott <cper...@pacific.net.sg> wrote in article
<5kc8ur$f...@netlab.cs.rpi.edu>...

>
> A CPU exception cannot be raised "anywhere and any time". Except in
> pathological cases, a floating point exception can be raised only by
> the execution of a floating point instruction, and such an instruction
> does have its position in the call graph. Practically all CPUs support
> hardware exceptions that generate an interrupt, causing an interrupt
> handler to be invoked in a manner very similar to a subroutine call.
> There is no reason why an interrupt handler cannot produce a C++
> exception.

Even if you discount truly asynchronous exceptions like attention and
termination signals, you still can't generally map CPU exceptions to C++
exceptions. What's left are typically access-violation and
illegal-arithmetic exceptions. Access violations aren't something you can
typically do anything about in a high-level language; some operating
systems even require user programs to ignore them, or they will interfere
with the system's paging mechanism. Arithmetic exceptions aren't totally
asynchronous, but given the high parallelism found even in single
microprocessors, they often aren't synchronous "enough" to deal with in a
high-level language; they aren't practical to handle because it's quite
tricky to restore the processor to a consistent state once the exception
occurs. True, there are special cases where you could handle either of
these by mapping them to C++ exceptions, on some systems. However, it's not
generally useful to think that hardware exceptions have any sort of mapping
into language exceptions, at least not given the current implementations of
hardware exceptions.
--
Bradd W. Szonye
bra...@concentric.net
http://www.concentric.net/~Bradds

Steve Clamage

unread,
May 4, 1997, 3:00:00 AM5/4/97
to

Chris Perrott wrote:
>
> Gerhard Huebner wrote:
> >
> > Chris Perrott wrote:
> >
> > > This is very strange. I see C++ exceptions as an abstraction of the
> > > CPU exceptions,
>
> > It is
> > not possible to "convert" CPU exceptions into C++ exceptions because an
> > exception is thrown with a "throw" statement in the C++ source code,
> > whereas a CPU exception can be raised anywhere and anytime. The C++
> > exception must be thrown from somewhere within the call graph because
> > the exception handlers that "catch" the exception must be on a higher
> > level in the call graph hierarchy than the "throw" statements in order
> > to be able to intercept them.
>
> A CPU exception cannot be raised "anywhere and any time". Except in
> pathological cases, a floating point exception can be raised only by
> the execution of a floating point instruction, and such an instruction
> does have its position in the call graph. Practically all CPUs support
> hardware exceptions that generate an interrupt, causing an interrupt
> handler to be invoked in a manner very similar to a subroutine call.
> There is no reason why an interrupt handler cannot produce a C++
> exception.
>
> It would be nice if someone other than Gerhard would comment on this...

OK, I will. :-)

First, are we discussing what some C++ implementation might choose
to do, or are we discussing what the C++ standard should require?

An implementation might choose to convert various CPU traps into
C++ exceptions which a program could catch. Such behavior is
certainly allowed.

Should you expect this behavior? No, because the standard does
not require it. Should the C++ standard require it? IMHO, no.

C++ exceptions by design are completely synchronous, and can
occur only at well-defined places in program execution.
In particular, they cannot occur during a function prologue or
epilogue when the stack is in an indeterminate state.

Can a general interrupt be converted into a C++ exception? No,
because in general interrupts are asynchronous. Even apparently
synchronous traps, like floating-point errors, might not in fact
be synchronous if the system uses a separate FPU.

Even if a particular interrupt happens synchronously, like invalid
pointer dereference, you have the question of how interrupts are
implemented on the platform. Typically they are implemented without
regard for C++. The C and C++ standards place no requirements on
the platform's interrupt mechanism, since platforms vary so widely.
If interrupt handlers run in their own address space with their own
stack, it is unlikely that exiting the handler via a thrown
exception would work.

CPU traps and platform interrupt mechanisms are deliberately
outside the regime of the C and C++ standards. Requiring particular
handling of interrupts would often mean that a C++ implementation
must be incompatible with either the standard or with its platform.
--
Steve Clamage, stephen...@eng.sun.com

Peter Hart

unread,
May 4, 1997, 3:00:00 AM5/4/97
to

Chris Perrott <cper...@pacific.net.sg> wrote:

>Gerhard Huebner wrote:
>>
>> Chris Perrott wrote:
>>
>> > This is very strange. I see C++ exceptions as an abstraction of the
>> > CPU exceptions,
>
>> It is
>> not possible to "convert" CPU exceptions into C++ exceptions because an
>> exception is thrown with a "throw" statement in the C++ source code,
>> whereas a CPU exception can be raised anywhere and anytime. The C++
>> exception must be thrown from somewhere within the call graph because
>> the exception handlers that "catch" the exception must be on a higher
>> level in the call graph hierarchy than the "throw" statements in order
>> to be able to intercept them.
>
>A CPU exception cannot be raised "anywhere and any time". Except in
>pathological cases, a floating point exception can be raised only by
>the execution of a floating point instruction, and such an instruction
>does have its position in the call graph. Practically all CPUs support
>hardware exceptions that generate an interrupt, causing an interrupt
>handler to be invoked in a manner very similar to a subroutine call.
>There is no reason why an interrupt handler cannot produce a C++
>exception.

I can see one good reason: if an interrupt handler can throw an
exception, this means that an exception can occur *anywhere* in the
code. Which could easily mean that the compiled code is half-way
through doing something, and everything is in an inconsistent state.
For instance, memory allocation typically takes more than a single
instruction to complete. The C++ environment is probably in an
inconsistent state during this time period. The raising of an
exception (and subsequent deletion of the half-allocated memory) is
unlikely to work very well.... :-). So in the general case this is
definitely unacceptable. In special cases it *may* be acceptable, but
personally, I'd want to be pretty sure....

>It would be nice if someone other than Gerhard would comment on this...

Happy now :-) ?

-Peter.
'Waste Please' - Exhortation on bins in DisneyWorld....
------------------------------------------------------------------------------
Peter Hart: ze...@one.net, 10604...@compuserve.com. Voice: +1-513-579-9957
135, Garfield Place Apt#423, Cincinnati OH45202, USA.

Bjarne Stroustrup

unread,
May 4, 1997, 3:00:00 AM5/4/97
to

Chris Perrott <cper...@pacific.net.sg> writes:

> A CPU exception cannot be raised "anywhere and any time". Except in
> pathological cases, a floating point exception can be raised only by
> the execution of a floating point instruction, and such an instruction
> does have its position in the call graph. Practically all CPUs support
> hardware exceptions that generate an interrupt, causing an interrupt
> handler to be invoked in a manner very similar to a subroutine call.
> There is no reason why an interrupt handler cannot produce a C++
> exception.

But, in a highly pipelined machine, are the CPU exception guaranteed to
occur before any instructions occur that are unrelated to the one causing
the exception but after that instruction in the program text? My impression
is that on many architectures cpu exceptions do not occur at easily
predicatble points relative to the instruction stream (because there isn't
a single well-defined instruction stream). You can make cpu exceptions
predicatble (as described here), but only at a cost of a very significant
slowdown in speed.

This may or may not be true on the machine you are currently using, but
it is an important notion that has to be taken into account when specifying
language features.

- Bjarne

Bjarne Stroustrup, AT&T Research, http://www.research.att.com/~bs/homepage.html

Bill Leonard

unread,
May 4, 1997, 3:00:00 AM5/4/97
to

In article <5kc8ur$f...@netlab.cs.rpi.edu>, Chris Perrott

<cper...@pacific.net.sg> writes:
>
> It would be nice if someone other than Gerhard would comment on this...

Okay, I'll take the bait. :-)

First, let's make one thing perfectly clear: The C++ standard does not
mandate that errors such as floating point arithmetic faults or memory
referencing errors result in exceptions. Therefore, if your program relies
on that behavior, it is not a standard-conforming program.

> A CPU exception cannot be raised "anywhere and any time". Except in
> pathological cases, a floating point exception can be raised only by
> the execution of a floating point instruction, and such an instruction
> does have its position in the call graph.

That much is true.

> Practically all CPUs support
> hardware exceptions that generate an interrupt, causing an interrupt
> handler to be invoked in a manner very similar to a subroutine call.

"Practically all" isn't good enough if you're writing a standard. :-)

There are many widely-used CPUs that do not support the ability to
*precisely* determine the instruction that caused a floating-point
exception. (The Motorola M88100 is an example I am familiar with). In
order to be able to do this, the compiler must emit special instructions,
which can slow down execution dramatically. Essentially, one must give up
a great deal of the parallelism the chip is capable of in order to get
precise information about exceptions.

> There is no reason why an interrupt handler cannot produce a C++
> exception.

There is if the compiler didn't prepare enough information for the
exception handling mechanism to be able to correctly unwind the stack. One
of the advantages of C++ exceptions over, say, Ada, is that C++ exceptions
are *only* generated by explicit programming constructs (in a
standard-conforming program), so the compiler need not have to be concerned
about exceptions occurring at just about any instruction it generates. Ada
compilers and runtimes have to do a lot of extra work in order to be able
to support exceptions caused by hardware faults. (An especially difficult
one is a memory fault caused by running out of stack space, because that
usually happens while you are setting up the stack frame for a procedure.
That's a bad time to want to unwind the call stack.)

Obviously, it *can* be done, but at some considerable expense, so the
standard doesn't *mandate* it. If a particular implementation wants to do
it, fine, but you'd better not rely on it if you want your program to be
portable.

--
Bill Leonard
Concurrent Computer Corporation
2101 W. Cypress Creek Road
Fort Lauderdale, FL 33309
Bill.L...@mail.ccur.com

These opinions and statements are my own and do not necessarily reflect the
opinions or positions of Concurrent Computer Corporation.

------------------------------------------------------------------------------
If I had my life to live over again, I think I *would* believe in
reincarnation.
------------------------------------------------------------------------------

Oleg Zabluda

unread,
May 5, 1997, 3:00:00 AM5/5/97
to

Bradd W. Szonye <bra...@concentric.net> wrote:
: Even if you discount truly asynchronous exceptions like attention and

: termination signals, you still can't generally map CPU exceptions to C++
: exceptions. What's left are typically access-violation and
: illegal-arithmetic exceptions. Access violations aren't something you can
: typically do anything about in a high-level language; some operating
: systems even require user programs to ignore them, or they will interfere
: with the system's paging mechanism. Arithmetic exceptions aren't totally
: asynchronous, but given the high parallelism found even in single
: microprocessors, they often aren't synchronous "enough"

This is usually a hardware problem. Even an OS knows nothing about
"parallel structure" of a single CPU.

: to deal with in a high-level language;

C++ is a low-level language.

: they aren't practical to handle because it's quite


: tricky to restore the processor to a consistent state once the exception
: occurs.

This depends on the exception, but this is not our problem. When it
can be done, we can do it, when it can't possibly be done, we
will not be given a chance to interfere by the CPU/OS.

: True, there are special cases where you could handle either of


: these by mapping them to C++ exceptions, on some systems. However, it's not
: generally useful to think that hardware exceptions have any sort of mapping
: into language exceptions, at least not given the current implementations of
: hardware exceptions.

There is definetily a whole class of arithemtic exceptions that
can be converted to C++ exceptions. I would even say all of them,
because they all happen in a well-defined place. Examples are
over/underflow, division by zero, extracting square root from a
negative number and so on.

Let's take overflow for example. If you implement your own arithmetic
types, you can check the relevant CPU flag bit right after the '+' and
see if an overflow occured, and throw an exception if it did.

Oleg.
--
Life is a sexually transmitted, 100% lethal disease.

Oleg Zabluda

unread,
May 5, 1997, 3:00:00 AM5/5/97
to

Steve Clamage <stephen...@Eng.Sun.COM> wrote:
: Can a general interrupt be converted into a C++ exception? No,

: because in general interrupts are asynchronous. Even apparently
: synchronous traps, like floating-point errors, might not in fact
: be synchronous if the system uses a separate FPU.

Even if does, it's CPU's job to undo anything it did in between
the FPU instruction was fetched from the instruction stream and
when a floating point exception occurs.

>From an outside of CPU, it always seems as if a CPU reads an
instruction stream one-by-one, and executes them one-by-one.
A CPU will never let you see what it has done if it was supposed
to happen after an FPU instruction caused an exception.

Oleg Zabluda

unread,
May 5, 1997, 3:00:00 AM5/5/97
to

Bjarne Stroustrup <b...@research.att.com> wrote:
: But, in a highly pipelined machine, are the CPU exception guaranteed


to
: occur before any instructions occur that are unrelated to the one
causing
: the exception but after that instruction in the program text? My
impression
: is that on many architectures cpu exceptions do not occur at easily
: predicatble points relative to the instruction stream (because there
isn't
: a single well-defined instruction stream). You can make cpu exceptions
: predicatble (as described here), but only at a cost of a very
significant
: slowdown in speed.

That's correct. There is usually a huge performance hit if
instructions in the parallel pipelines have to be undone,
if an instruction, that was supposed to be executed before
them, causes an exception. Same is true if a CPU guessed a
branch wrong, or did any other out-of-order execution wrong.

Still, from an outside of a CPU it always seems as if the
instructions are executed in order.

BTW, this is one of the reason why I like C++ exceptions so
much. Because they [have a potential to] make code (especially
in conjunction with inline functions) much more linear, therefore
improving performance on modern pipelined, parallel,
branch-predicting, out-of-order-executing :-) CPU's. I have yet to
hear from someone who would either confirm my enthusiasm, or
tell me that I'm too optimistic.

: This may or may not be true on the machine you are currently using,


but
: it is an important notion that has to be taken into account when
specifying
: language features.

Are you aware of any CPU that allows the fact that instructions
are actually executed out of order, escape and become visible,
under any circumstances?

Brad Stuart

unread,
May 5, 1997, 3:00:00 AM5/5/97
to

Peter Hart (ze...@one.net) wrote:
: Chris Perrott <cper...@pacific.net.sg> wrote:

: I can see one good reason: if an interrupt handler can throw an


: exception, this means that an exception can occur *anywhere* in the
: code. Which could easily mean that the compiled code is half-way
: through doing something, and everything is in an inconsistent state.
: For instance, memory allocation typically takes more than a single
: instruction to complete. The C++ environment is probably in an
: inconsistent state during this time period. The raising of an
: exception (and subsequent deletion of the half-allocated memory) is
: unlikely to work very well.... :-). So in the general case this is
: definitely unacceptable. In special cases it *may* be acceptable, but
: personally, I'd want to be pretty sure....

Well, your interrupt handler isn't working very well if it leaves
the C++ world in an inconsistent state and returns control to the
program. Better to let the program die than to "handle" the problem
by merely converting it to an exception.

Aside from that, it seems pretty dangerous to use an interrupt handler
to throw an exception. On my system, the behavior or the program is
clearly defined if the handler returns normally, and if it calls
exit(). Another man-page states that the signal handler executes on
the "same stack" as the main program. This would seem to indicate that
throwing might work as expected. That's not enough of a guarantee to
write any code with, though.

: >It would be nice if someone other than Gerhard would comment on this...


--
| Brad Stuart br...@cfar.umd.edu
| Center for Automation Research
| University of Maryland, College Park

Andrew Koenig

unread,
May 6, 1997, 3:00:00 AM5/6/97
to

In article <5kkk0v$a...@netlab.cs.rpi.edu> Oleg Zabluda <zab...@math.psu.edu> writes:

> Steve Clamage <stephen...@Eng.Sun.COM> wrote:
> : Can a general interrupt be converted into a C++ exception? No,
> : because in general interrupts are asynchronous. Even apparently
> : synchronous traps, like floating-point errors, might not in fact
> : be synchronous if the system uses a separate FPU.

> Even if does, it's CPU's job to undo anything it did in between
> the FPU instruction was fetched from the instruction stream and
> when a floating point exception occurs.

That depends on the CPU. It have certainly seen processors in which
if you want floating-point processing to be synchronized with the rest
of processing, you have to insert synchronization instructions that
slow the machine down dramatically.
--
--Andrew Koenig
a...@research.att.com
http://www.research.att.com/info/ark

Paul D. DeRocco

unread,
May 6, 1997, 3:00:00 AM5/6/97
to

Bjarne Stroustrup wrote:
>
> But, in a highly pipelined machine, are the CPU exception guaranteed to
> occur before any instructions occur that are unrelated to the one causing
> the exception but after that instruction in the program text? My impression
> is that on many architectures cpu exceptions do not occur at easily
> predicatble points relative to the instruction stream (because there isn't
> a single well-defined instruction stream). You can make cpu exceptions
> predicatble (as described here), but only at a cost of a very significant
> slowdown in speed.
>
> This may or may not be true on the machine you are currently using, but
> it is an important notion that has to be taken into account when specifying
> language features.

True in general. Many modern CPUs, including the Pentium, execute
speculatively, but don't "commit" the results of the instruction until
all phases of it are complete. If an instruction generates an exception,
such as a page fault, then all subsequent instructions that have been
speculatively executed are discarded, thus making it all behave "as if"
everything was executed sequentially. However, there are probably some
really vicious RISC machines out there that aren't so
programmer-friendly.

Anyway, as I pointed out in another post, I've found it useful to be
able to convert things like unknown page faults into exceptions, because
in most cases it allows my software to display an error message to the
user containing the address of the faulting instruction, and then
continue the program. I get a report from the user that actually helps
me find the bug, and they get a program that doesn't completely die. For
this to work, it is necessary to not use (or disable the functionality
of) exception specifications, since they'd turn all my "internal error"
exceptions into calls to unexpected(), thus defeating their purpose. I'd
hate to see the standard make it impossible to do this.

--

Ciao,
Paul

(Please send e-mail to mailto:pder...@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Runu Knips

unread,
May 6, 1997, 3:00:00 AM5/6/97
to

In article <5kgau5$o...@netlab.cs.rpi.edu>,
"Paul D. DeRocco" <strip_these_w...@ix.netcom.com> writes:
:
: Under 32-bit DPMI, I've successfully installed handlers for general

: protection faults and unknown page faults that turn these into C++
: exceptions. I throw an error message that says something like
:
: Internal error at 0197:00411926
:
: which winds up being caught at the top level of the program and
: displayed to the user. That way, instead of the program simply dying, or
: reporting an information-free message, it gives the user a piece of data
: which often helps me find the bug.
:
: This, however, makes it almost impossible to use exception
: specifications anywhere, since protection faults can happen any time you
: give any function a null, dangling or uninitialized pointer, or even an
: out-of-range index. With exception specifications, all these unexpected
: exceptions would in fact call unexpected(), and wind up aborting the
: program. For this reason, I don't like exception specifications, and
: prefer not to use them at all.
:

Well, but why do you even use exceptions in this case ? If you already
know you want to shut down the whole program after a null pointer
reference or such, why don't you just print the message in the SIGSEGV
handler (or the analogon for it under DPMI) and end the program by
calling _exit() ?

David Vandevoorde

unread,
May 6, 1997, 3:00:00 AM5/6/97
to

Oleg Zabluda wrote:
>
> Steve Clamage <stephen...@Eng.Sun.COM> wrote:
> : Can a general interrupt be converted into a C++ exception? No,
> : because in general interrupts are asynchronous. Even apparently
> : synchronous traps, like floating-point errors, might not in fact
> : be synchronous if the system uses a separate FPU.
>
> Even if does, it's CPU's job to undo anything it did in between
> the FPU instruction was fetched from the instruction stream and
> when a floating point exception occurs.
>
> >From an outside of CPU, it always seems as if a CPU reads an
> instruction stream one-by-one, and executes them one-by-one.
> A CPU will never let you see what it has done if it was supposed
> to happen after an FPU instruction caused an exception.

That's not quite right. Although some CPUs do exhibit the
property you describe, several deeply pipelined and/or super-
scalar processor cannot support "precise exceptions" for
floating-point operations on their own (a precise exception
is one which makes a clean cut between instructions preceding
it and which will be allowed to complete, and instructions
following it which shouldn't semantically affect the machine
state). Usually, such CPUs have a mechanism to trap to a
software handler that will can help restore preciseness
(I believe "precise exceptions" are required in IEEE754
arithmetic).

Supercomputers, for example, would likely run scientific C++
programs much more slowly if they had to support an exception
model as proposed (supercomputers tend to have a very
simplified exception model).

Daveed

Paul D. DeRocco

unread,
May 7, 1997, 3:00:00 AM5/7/97
to

Runu Knips wrote:
>
> Well, but why do you even use exceptions in this case ? If you already
> know you want to shut down the whole program after a null pointer
> reference or such, why don't you just print the message in the SIGSEGV
> handler (or the analogon for it under DPMI) and end the program by
> calling _exit() ?

Because I _don't_ want to terminate the program. I guess I neglected to
make clear that the "top level" of my program, where I display the error
message, is a loop that waits for further input. I used this particular
technique in a stage lighting controller that is controlled in part by
entering commands on a rather large keypad. When a bug causes a
protection fault, the user would rather the individual operation was
aborted than the entire program, and it makes sense if the exception
reports the physical address, so the user can relay it back to me.

The reason I throw an error message, instead of displaying an error
message and then throwing some fixed exception, is that I use the same
technique to report practically all errors, including user input errors:
I just format a string containing the message and throw it to the
top-level handler. Works great.

--

Ciao,
Paul

(Please send e-mail to mailto:pder...@ix.netcom.com instead of the
return address, which has been altered to foil junk mail senders.)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

kjh...@mmm.com

unread,
May 7, 1997, 3:00:00 AM5/7/97
to

Paul D. DeRocco wrote:

[snip]

> Anyway, as I pointed out in another post, I've found it useful to be
> able to convert things like unknown page faults into exceptions, because
> in most cases it allows my software to display an error message to the
> user containing the address of the faulting instruction, and then
> continue the program. I get a report from the user that actually helps

How does this conversion take place? If, for example, you set up a
signal handler and throw from it, this is not guaranteed to work.

> me find the bug, and they get a program that doesn't completely die. For
> this to work, it is necessary to not use (or disable the functionality
> of) exception specifications, since they'd turn all my "internal error"
> exceptions into calls to unexpected(), thus defeating their purpose. I'd
> hate to see the standard make it impossible to do this.
--

Kevin J. Hopps, Imation kjh...@imation.com
My opinions are my own. I speak neither for Imation nor 3M.

Bill Leonard

unread,
May 8, 1997, 3:00:00 AM5/8/97
to

In article <5kknul$b...@netlab.cs.rpi.edu>, Oleg Zabluda <zab...@math.psu.edu> writes:
> Are you aware of any CPU that allows the fact that instructions
> are actually executed out of order, escape and become visible,
> under any circumstances?

Yes, the Motorola M88100. Some of the early MIPS RISC processors did too,
I believe, but I am absolutely certain about the M88100.

And who knows what tomorrow's processors will do?

--
Bill Leonard
Concurrent Computer Corporation
2101 W. Cypress Creek Road
Fort Lauderdale, FL 33309
Bill.L...@mail.ccur.com

These opinions and statements are my own and do not necessarily reflect the
opinions or positions of Concurrent Computer Corporation.

------------------------------------------------------------------------------
If I had my life to live over again, I think I *would* believe in
reincarnation.
------------------------------------------------------------------------------

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Paul D. DeRocco

unread,
May 8, 1997, 3:00:00 AM5/8/97
to

kjh...@mmm.com wrote:
>
> > Anyway, as I pointed out in another post, I've found it useful to be
> > able to convert things like unknown page faults into exceptions, because
> > in most cases it allows my software to display an error message to the
> > user containing the address of the faulting instruction, and then
> > continue the program. I get a report from the user that actually helps
>
> How does this conversion take place? If, for example, you set up a
> signal handler and throw from it, this is not guaranteed to work.

It's system-dependent. In DPMI, the layout of the stack on entry to the
fault handler is documented, and it's possible to modify it so that the
fault handler returns not to the place where the fault occurred but to a
helper function that throws the exception.

--

Ciao,
Paul

(Please remove the "strip_these_words_" prefix from the return


address, which has been altered to foil junk mail senders.)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Igor Siemienowicz

unread,
May 12, 1997, 3:00:00 AM5/12/97
to

Bernard Badger <bba...@jade.ssd.hcsc.com> wrote in article
<5kgaqa$o...@netlab.cs.rpi.edu>...

> I agree that hardware exceptions can be mapped into the software
> exception mechanism. I believe that Ada has this capability. I
> cannot judge whether converting hardware exceptions is even allowed by
> the standard. I'm only saying that the concept is plausible, and has
> precedence in other languages. It does have its problems, because
> it's hard to guarantee that recovery code won't raise more exceptions.

> I think that this turns somewhat on the ambiguous phrase "in general".


> I believe that it is being used here in the sense of,
> "there is no pre-defined relationship between exceptions and CPU
> exceptions
> which is required in all cases."
> This is in contrast to the possible meaning, "in most cases, CPU
> exceptions
> aren't mapped into C++ exceptions."
>
> Even if CPU exceptions exist, it is no doubt highly implementation
> dependent
> how they may be mapped into the exception handling mechanism.

Visual C++ v4.2 allows hardware exceptions to be thrown as C++
exceptions.
I'm a little new to it, but when I've been naughty, and tried to write
to
an unitialised pointer, I get a protection exception that is catchable.
It's quite useful, actually...

I think it would be sorta nice to have a set of 'standard' hardware
exceptions that were thrown when certain conditions arose. You could
have
low-level code that mapped the hardware conditions to the standard
exceptions to keep everything nice a portable.

Just a thought...
--
Igor Siemienowicz
ig...@werple.net.au

James Kanze

unread,
May 12, 1997, 3:00:00 AM5/12/97
to

Oleg Zabluda <zab...@math.psu.edu> writes:

|> Bjarne Stroustrup <b...@research.att.com> wrote:
|> : But, in a highly pipelined machine, are the CPU exception
guaranteed
|> to
|> : occur before any instructions occur that are unrelated to the one
|> causing
|> : the exception but after that instruction in the program text? My
|> impression
|> : is that on many architectures cpu exceptions do not occur at
easily
|> : predicatble points relative to the instruction stream (because
there
|> isn't
|> : a single well-defined instruction stream). You can make cpu
exceptions
|> : predicatble (as described here), but only at a cost of a very
|> significant
|> : slowdown in speed.
|>

|> That's correct. There is usually a huge performance hit if
|> instructions in the parallel pipelines have to be undone,
|> if an instruction, that was supposed to be executed before
|> them, causes an exception. Same is true if a CPU guessed a
|> branch wrong, or did any other out-of-order execution wrong.

I suppose one could implement something like this. Traditionally,
however, it hasn't been done. The delays mentioned come from having to
insert additional synchronization instructions after each floating point
operation, and from having to wait until the floating point operation
was finished before doing anything else was done.

|> Still, from an outside of a CPU it always seems as if the
|> instructions are executed in order.
|>
|> BTW, this is one of the reason why I like C++ exceptions so
|> much. Because they [have a potential to] make code (especially
|> in conjunction with inline functions) much more linear, therefore
|> improving performance on modern pipelined, parallel,
|> branch-predicting, out-of-order-executing :-) CPU's. I have yet to
|> hear from someone who would either confirm my enthusiasm, or
|> tell me that I'm too optimistic.

With current compilers, you're almost certainly too optimistic:-). In
theory, however, this could result in some speed up, although unless the
implementation accepts the idea of a (at least partially) asynchronous
exception, I don't think it will be possible to gain much.

|> : This may or may not be true on the machine you are currently


using,
|> but
|> : it is an important notion that has to be taken into account when
|> specifying
|> : language features.
|>

|> Are you aware of any CPU that allows the fact that instructions
|> are actually executed out of order, escape and become visible,
|> under any circumstances?

All processors of the Intel 80x86 family, from the 8086/8087 on. I
think that the Motorola 680x0's worked the same way, too, although I'm
not 100% sure.

Note that with the 8086/8087, the usual procedure was to generate a
fwait instruction (which waited as long as the 8087 was busy) *before*
each floating point instruction, not after. Thus, for example, if a
function returned a floating point value, the actual calculation of the
value could be occuring during the function return, when the stack frame
was not correctly set up. It would be very difficult to implement a
floating point error as an exception under these conditions.

--
James Kanze home: ka...@gabi-soft.fr +33 (0)1 39 55 85
62
office: ka...@vx.cit.alcatel.fr +33 (0)1 69 63 14
54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles
France
-- Conseils en informatique industrielle --

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Paul D. DeRocco

unread,
May 12, 1997, 3:00:00 AM5/12/97
to

James Kanze wrote:
>
> Note that with the 8086/8087, the usual procedure was to generate a
> fwait instruction (which waited as long as the 8087 was busy) *before*
> each floating point instruction, not after. Thus, for example, if a
> function returned a floating point value, the actual calculation of the
> value could be occuring during the function return, when the stack frame
> was not correctly set up. It would be very difficult to implement a
> floating point error as an exception under these conditions.

Compilers I've used stick an FWAIT before the RET in any function that
returns a floating point value, either directly or through a pointer.

--

Ciao,
Paul

(Please remove the "strip_these_words_" prefix from the return
address, which has been altered to foil junk mail senders.)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Oleg Zabluda

unread,
May 13, 1997, 3:00:00 AM5/13/97
to

James Kanze <james-alb...@vx.cit.alcatel.fr> wrote:
: Oleg Zabluda <zab...@math.psu.edu> writes:

: |> That's correct. There is usually a huge performance hit if


: |> instructions in the parallel pipelines have to be undone,
: |> if an instruction, that was supposed to be executed before
: |> them, causes an exception. Same is true if a CPU guessed a
: |> branch wrong, or did any other out-of-order execution wrong.

: I suppose one could implement something like this. Traditionally,
: however, it hasn't been done. The delays mentioned come from having to
: insert additional synchronization instructions after each floating point
: operation, and from having to wait until the floating point operation
: was finished before doing anything else was done.

Ok, many people pointed that floating point exceptions are
asynchronous on may CPU's. But when I wrote the paragraph above,
I was thinking more of plain integer exceptions - overflow for
example. Is there any reason why those can't be converted into C++
exceptions?

Oleg.
--
Life is a sexually transmitted, 100% lethal disease.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

James Kanze

unread,
May 14, 1997, 3:00:00 AM5/14/97
to

Oleg Zabluda <zab...@math.psu.edu> writes:

|> James Kanze <james-alb...@vx.cit.alcatel.fr> wrote:
|> : Oleg Zabluda <zab...@math.psu.edu> writes:
|>
|> : |> That's correct. There is usually a huge performance hit if
|> : |> instructions in the parallel pipelines have to be undone,
|> : |> if an instruction, that was supposed to be executed before
|> : |> them, causes an exception. Same is true if a CPU guessed a
|> : |> branch wrong, or did any other out-of-order execution wrong.
|>
|> : I suppose one could implement something like this. Traditionally,
|> : however, it hasn't been done. The delays mentioned come from having to
|> : insert additional synchronization instructions after each floating point
|> : operation, and from having to wait until the floating point operation
|> : was finished before doing anything else was done.
|>
|> Ok, many people pointed that floating point exceptions are
|> asynchronous on may CPU's. But when I wrote the paragraph above,
|> I was thinking more of plain integer exceptions - overflow for
|> example. Is there any reason why those can't be converted into C++
|> exceptions?

Only that most processors don't generate a hardware exception for
integer overflow:-(.

A good compiler could generate a test for overflow after each operation,
and generate the exception when necessary. This would entail
significant run-time overhead. I would still like to see it as the
default, to be turned off if performance became a problem in production
code. (A good optimizer could probably eliminate a significant number
of the tests.)

--
James Kanze home: ka...@gabi-soft.fr +33 (0)1 39 55 85 62
office: ka...@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Oleg Zabluda

unread,
May 15, 1997, 3:00:00 AM5/15/97
to

James Kanze <james-alb...@vx.cit.alcatel.fr> wrote:
: Oleg Zabluda <zab...@math.psu.edu> writes:

: |> Ok, many people pointed that floating point exceptions are


: |> asynchronous on may CPU's. But when I wrote the paragraph above,
: |> I was thinking more of plain integer exceptions - overflow for
: |> example. Is there any reason why those can't be converted into C++
: |> exceptions?

: Only that most processors don't generate a hardware exception for
: integer overflow:-(.

Sorry, it was a bad wording on my part. They don't generate exceptions,
but they set an overflow bit somewhere. At least this is what my
80x86 CPU guru friend told me.

So what I had in mind was to create, say, an Int class, which will
throw if an overflow occurs. It'll detect it if the bit is set. To
do it or not, can be chosen by the programmer by setting up
some static variable through a class interface.

If the bit is sticky (??), it can be checked only once, at the end
of some calculatons. It'll introduce a minimal overhead, and the
result is IMHO good enough: the current batch of calculations is wrong.
At the very least, it can simply be logged.

Oleg.
--
Life is a sexually transmitted, 100% lethal disease.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Paul D. DeRocco

unread,
May 17, 1997, 3:00:00 AM5/17/97
to

Oleg Zabluda wrote:
>
> Sorry, it was a bad wording on my part. They don't generate exceptions,
> but they set an overflow bit somewhere. At least this is what my
> 80x86 CPU guru friend told me.
>
> So what I had in mind was to create, say, an Int class, which will
> throw if an overflow occurs. It'll detect it if the bit is set. To
> do it or not, can be chosen by the programmer by setting up
> some static variable through a class interface.
>
> If the bit is sticky (??), it can be checked only once, at the end
> of some calculatons. It'll introduce a minimal overhead, and the
> result is IMHO good enough: the current batch of calculations is wrong.
> At the very least, it can simply be logged.

FYI, the x86 has an overflow flag, but it isn't sticky. What's more, for
adds and subtracts, it indicates the result of signed arithmetic only.
There is, however, a one-byte instruction that generates an interrupt if
the flag is set. On the 486 it took 3 clocks (for no interrupt), and
probably isn't much better optimized on the Pentium, so it's rarely
used.

What I'd like even more than an overflow trap is an integer NaN,
implemented as the largest negative number, that would be produced by
any error, and propagate through all integer calculations.

--

Ciao,
Paul

(Please remove the "strip_these_words_" prefix from the return
address, which has been altered to foil junk mail senders.)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Alf P. Steinbach

unread,
May 18, 1997, 3:00:00 AM5/18/97
to

Paul D. DeRocco wrote:
> What I'd like even more than an overflow trap is an integer NaN,
> implemented as the largest negative number, that would be produced by
> any error, and propagate through all integer calculations.

Well, at the risk of being permanently excluded from this newsgroup,
there is such a beast. Namely x87 80-bit integers, which I think
(99% sure, but reason for caution here) are also IEEE standard.
I don't know any C++ implementation supporting them, but old
Borland Pascal do... :-)

- Alf


--
[Reply address intentionally foiled, but workable for humans.]

James Kanze

unread,
May 20, 1997, 3:00:00 AM5/20/97
to

Oleg Zabluda <zab...@math.psu.edu> writes:

|> James Kanze <james-alb...@vx.cit.alcatel.fr> wrote:
|> : Oleg Zabluda <zab...@math.psu.edu> writes:
|>
|> : |> Ok, many people pointed that floating point exceptions are
|> : |> asynchronous on may CPU's. But when I wrote the paragraph above,
|> : |> I was thinking more of plain integer exceptions - overflow for
|> : |> example. Is there any reason why those can't be converted into C++
|> : |> exceptions?
|>
|> : Only that most processors don't generate a hardware exception for
|> : integer overflow:-(.
|>

|> Sorry, it was a bad wording on my part. They don't generate exceptions,
|> but they set an overflow bit somewhere. At least this is what my
|> 80x86 CPU guru friend told me.

It does. Most processors do.

|> So what I had in mind was to create, say, an Int class, which will
|> throw if an overflow occurs. It'll detect it if the bit is set. To
|> do it or not, can be chosen by the programmer by setting up
|> some static variable through a class interface.
|>
|> If the bit is sticky (??), it can be checked only once, at the end
|> of some calculatons. It'll introduce a minimal overhead, and the
|> result is IMHO good enough: the current batch of calculations is wrong.
|> At the very least, it can simply be logged.

First, the bit isn't sticky, so you have to check it after every
operation. Second, it isn't accessible from a high level language, so
you will have to write your class in assembler.

Most implementations of overflow checking arithmetic I've seen check the
operands before hand. Which is, or at least can be, expensive.

--
James Kanze home: ka...@gabi-soft.fr +33 (0)1 39 55 85 62
office: ka...@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Paul D. DeRocco

unread,
May 20, 1997, 3:00:00 AM5/20/97
to

Alf P. Steinbach wrote:
>
> Well, at the risk of being permanently excluded from this newsgroup,
> there is such a beast. Namely x87 80-bit integers, which I think
> (99% sure, but reason for caution here) are also IEEE standard.
> I don't know any C++ implementation supporting them, but old
> Borland Pascal do... :-)

The x87 coprocessor never supported 80-bit binary integers. It supports
64-bit integers (by appending the appropriate exponent and treating it
as a float), and 18-digit BCD integers, which, with a sign byte, takes
ten bytes. I believe it's the latter you're thinking of. However, when
the 18 BCD digits are converted to binary, they still fit into 64 bits.

[Just for the record: the IEEE standard only concerns floating point
types. None of the integral types supported by any floating point
processor are defined by this standard. -- jak ]

--

Ciao,
Paul

(Please remove the "strip_these_words_" prefix from the return
address, which has been altered to foil junk mail senders.)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Alf P. Steinbach

unread,
May 21, 1997, 3:00:00 AM5/21/97
to

Paul D. DeRocco wrote:
>
> Alf P. Steinbach wrote:
> >
> > Well, at the risk of being permanently excluded from this newsgroup,
> > there is such a beast. Namely x87 80-bit integers, which I think
> > (99% sure, but reason for caution here) are also IEEE standard.
> > I don't know any C++ implementation supporting them, but old
> > Borland Pascal do... :-)
>
> The x87 coprocessor never supported 80-bit binary integers. It supports
> 64-bit integers (by appending the appropriate exponent and treating it
> as a float), and 18-digit BCD integers, which, with a sign byte, takes
> ten bytes. I believe it's the latter you're thinking of. However, when
> the 18 BCD digits are converted to binary, they still fit into 64 bits.

You're right, the BP type I was referring to is/was a 64-bit integer
type, and it's represented in 8 bytes. Still quite good, though. For
some reason, "80 bits" stuck in my mind... Hm de dum.

>
> [Just for the record: the IEEE standard only concerns floating point
> types. None of the integral types supported by any floating point
> processor are defined by this standard. -- jak ]

Is there any de facto or industrial standard for integral types then? I
know, this is not C++ as such, but it relates to C++'s ability to access
and exploit the hardware of modern computers, in the same way that C was
tailored to the computers of the 1970's.

[I don't think that a standard for integral types was thought
necessary. As long as you don't overflow, the results are exact,
and thus the same on all machines. -- jak ]

- Alf

--
[Reply address intentionally foiled, but workable for humans.]

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

0 new messages