home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.acorn.tech
- Path: sparky!uunet!charon.amdahl.com!pacbell.com!ames!agate!doc.ic.ac.uk!mrccrc!warwick!pavo.csi.cam.ac.uk!jubilex!crj10
- From: crj10@phx.cam.ac.uk (Clive Jones)
- Subject: Re: Exception handling in C.
- In-Reply-To: bwc@waikato.ac.nz (Ug!)'s message of 9 Nov 92 13:50:23 +1300
- Message-ID: <1992Nov11.223824.9107@infodev.cam.ac.uk>
- Telephone-Messages: +44 223 33 4900
- Sender: news@infodev.cam.ac.uk (USENET news)
- Address: Christ's College, Cambridge CB2 3BU, ENGLAND.
- Nntp-Posting-Host: bourn.cl.cam.ac.uk
- Organization: 6am Digital Playground
- X-Furry-Character: Gerald_Duck
- References: <1992Nov9.135023.12048@waikato.ac.nz>
- Date: Wed, 11 Nov 1992 22:38:24 GMT
- Lines: 120
-
- In article <1992Nov9.135023.12048@waikato.ac.nz>, bwc@waikato.ac.nz (Ug!) writes:
- > I'd like to discuss a few things about what I am implementing at the moment,
- > first among them being the issue of exception handling in C.
-
- I will have exception handling available Real Soon Now in Desktop C. I intend
- to release it into the public domain, as part of a package of extra 'primitives'
- to alter the flow of control in C programs (or, I suppose, Pascal, or other
- APCS languages).
-
- The complete package will contain:
- Coroutines
- Vectors
- Exceptions
- (and possibly) Timer-activated pre-emptive triggering of functions.
- The combination of coroutines and pre-emptive function calls obviously combine
- to provide pre-emptive multitasking WITHIN a C program.
-
- > Exception handling is always a messy business, and C doesn't cope
- > particularly well with it, although in fact I've yet to meet a language
- > which does.
-
- C has *no* explicit mechanism for passing exceptions around in your programs -
- it only provides the signal and errno interfaces to the standard library and
- operating system. A cynic might say that even those are only there to aid
- portability, and not for the tidier programming style they engender. (-8
-
- Exceptions are handled well, IMO, by Modula-3, PL/1 and BBC Basic 4. Admittedly,
- the LOCAL/RESTORE ERROR pair of commands are primitive, but they do the
- business. Look at the other two languages as well if you want some ideas for
- nice exception systems.
-
- [...]
- > * exceptions should be interceptable. For instance, if I call a routine
- > to open a file, and the routine raises an exception if that file doesn't
- > exist, then an error message may not always be appropriate for that
- > situation. I should be able to intercept that exception, and in this
- > case, decide not to raise an error.
-
- In other words, you should be able to locally handle exceptions, as well as
- having the global handlers. This is, to my mind, the vital difference between
- a proper exceptions mechanism and a simple signal system.
-
- > * exceptions should not alter the normal flow of code. If you allow
- > an exception to land you somewhere else in the program, then you end
- > up with a mess that makes spaghetti look friendly. Instead, exceptions
- > should be coped with in a manner resembling interrupt handlers.
-
- The two halves of that seem to contradict. I agree with the first half, which
- basically means that an exception shouldn't let you go somewhere you couldn't
- go with a longjmp(), for example. However, this seems to contradict the idea of
- it behaving like an interrupt - i.e. calling some function when an exception
- occurs, thus breaking the normal flow of control.
-
- > Those were my base ideas for handling exceptions. What I came up with was
- > essentially each module registering a handler with an 'error' module. The
- > most recent registered handler is passed the exception first. If it doesn't
- > handle the exception, then the next most recent handler is called, and so on.
-
- Fair enough, for some uses...
-
- > How do other people cope with exceptions? Is there something I'm missing?
- > I've noticed that my way of doing adds the additional ability to cope well
- > with internationalisation, which is an added bonus.
-
- The structure I decided upon was as follows:
-
- 1) Each module can produce some anomalous circumstances. Classify these, and
- you ought to have "exception classes". Try and arrange it so that each of
- these exceptions can be expressed by a pointer to a struct, or similar.
-
- 2) For each of these, provide an extern function pointer to a handler. By
- default, have this pointing at something which just generates a textual
- error message, and passes it to an error handler function (which is just
- another extern function pointer, but one which is always fed a char *).
- The default function on this 'hook' should print the message to stderr and
- exit.
-
- 3) NOW - each module is standalone, and doesn't rely on any given exception
- mechanism. This means that in simple programs, you can forgo ANY exception
- system and save space. It also means that someone else can come along with
- their own pet exception handling system and bolt it on instead. However,
- then also supply...
-
- 4) An exceptions mechanism. Provide a standard function exception_raise(),
- for example, which can be set as the handler function for all the
- anomalous situations in any appropriate modules. Also provide an
- exception_handle() function, akin to setjmp(), which returns NULL when
- called directly, but a pointer to an exception if one is returned via
- it. Bind this up in some 'syntactic sugar' such as:
- #define try { if (exception_handle())
- #define except else { switch (exception_type())
- #define endtry exception_passon(); } exception_unhandle(); }
- ...so that you can catch exceptions in a tidy structure of the form:
- try
- {
- f = openfile("Spong", "r");
- }
- except
- {
- case ex_FILENOTFOUND:
- ...
- }
- endtry
-
- (Try substituting the macros above to see roughly how that would work!)
-
- Your exception_raise() function should then backtrace the stack until it
- finds an exception handler, and then call it. If it hits the end of the
- program, it should call some default function. You can use longjmp if
- you're not brave enough to write some assembler to do this.
-
- 5) For added spice, you could actually attach a vector to each of the
- anomalous condition handlers instead, and put the exception mechanism as
- one of the claimants of the vector. You could then do cunning things like
- report the exception to a different coroutine if the generating
- coroutine didn't handle it, etc. - you get the idea.
-
- Hope this is of *some* interest,
-
- --Clive.
-