Contents of an exception object

Discussion in 'C Programming' started by James Harris, May 28, 2014.

  1. James Harris

    James Harris Guest

    Although C has no support for exceptions it seems easy enough with some
    programming discipline to achieve a similar effect - or at least one that
    suits my purposes: basically to throw an exception at one level and catch it
    higher up the call stack.

    Where the exception is thrown I had in mind creating an object (i.e. a
    struct) to represent some details about the exception. My question is about
    what you guys would suggest to include in that object, i.e. things which are
    simple in C to include and yet potentially useful. To illustrate, the call
    to create the exception might be something like

    excep_throw( .... );

    This function would create an object to describe what was found to be wrong
    and then trigger the exception handling mechanism. The mechanism is
    unimportant here but what things would be good to include in the parens?
    Some possibilities:

    * the type of exception (an unsigned int)
    * the function name (as a string?)
    * __FILE__ and/or __LINE__ (if possible)
    * a message string
    * parameters (somehow)

    Any thoughts on that? Anyone already done something similar?

    James Harris, May 28, 2014
    1. Advertisements

  2. James Harris

    James Kuyper Guest

    For C99 and later, initialize the function name from __func__.
    When throwing from inside a loop, the current value of the loop counter
    would also provide some useful information.
    I would think it would be more useful to restrict your attention to the
    values of variables (whether or not they are parameters) appearing in
    the condition expression, that have more than one value that could
    trigger the condition, could be useful.
    James Kuyper, May 28, 2014
    1. Advertisements

  3. [...]

    This is available in C99 and later as __func__.

    (This is an implicitly declared identifier, not a macro.)
    Keith Thompson, May 28, 2014
  4. A bit-shuffling function, which doesn't do IO, can fail because it runs
    out of memory. Strictly, that's the only failure possible. If it fails
    because of an internal programming error then by definition there can be
    no correct behaviour for the program.
    However it's useful to allow a "parse error" to cover functions which
    allow complex language-like input, which is almost as hard to check
    for correctness as to implement the function. You might also allow
    a "numerical overflow" error, though mostly that's either a sign of
    an internal programming error (numerical instability), or corrupt

    I think that just about covers bit shuffling function errors. Most
    bit shuffling functions can't have any errors because they are defined
    for all patterns of input bits. That's a major reason for separating
    them out.

    IO procedures can fail in all sorts of ways, because each hardware
    device is different and has different things which can physically go
    wrong with it. For filesystem type IO, basically you've got
    "file not found", "file cannot be created", and a generic "IO error"
    meaning that the device is reporting a read/write fail.
    Then you've also got parse errors. Unlike bit shuffling functions,
    where functions that do non-trivial parsing are a rarity, most procedures
    that accept a file as input can fail in multiple ways because
    the file format is not coherent. If input is a text file, often it's
    very useful to the user to report the offending line. If it's a binary
    file, really all you can do is report "file corrupt".

    For non-file system IO, really the failure modes are open-ended. There's
    no restriction on the number of devices which might potentially be
    attached to a computer, and they can fail in many ways meaningful
    to the user. Printers can run out of ink or paper, microphones can
    be pushed beyond their dynamic range, radio links can become too
    faint, keyboards can send unrecognised characters, and so on.
    Malcolm McLean, May 28, 2014
  5. James Harris

    Stefan Ram Guest The feclearexcept function The fegetexceptflag function The feraiseexcept function The fesetexceptflag function The fetestexcept function

    Stefan Ram, May 28, 2014
  6. James Harris

    James Kuyper Guest

    Those are for floating point exceptions; he's probably looking for a
    more general-purpose mechanism.
    James Kuyper, May 28, 2014
  7. James Harris

    Kaz Kylheku Guest

    Most mainstream compilers do not have any such a thing.

    I'd buy the claim that most compilers **for Win32** have this.

    Structured Exception Handling is a Windows feature.
    setjmp and longjmp, not "jump".
    Kaz Kylheku, May 28, 2014
  8. James Harris

    Kaz Kylheku Guest

    I wrote an exception library for C more than 15 years ago.

    It lives here:

    And is documented here:

    It was selected for use in the Wireshark program many years ago:;a=blob;f=epan/except.c;hb=HEAD

    When Wireshark's packet parsers ("dissectors") encounter a garbage packet (for
    instance, a truncated one), they throw an exception. (And probably there are
    other uses of this in the codebase.)
    Kaz Kylheku, May 28, 2014
  9. [...]

    So you're still insisting on using your own idiosyncratic definitions
    of the words "function" and "procedure"?
    Keith Thompson, May 29, 2014
  10. James Harris

    Ike Naar Guest

    You mean it can't fail because of stack overflow, exceeded cpu-time quota,
    a high temperature condition caused by a stuck fan or whatnot? Mmmm.

    But let's forget about that and examine the phrase 'bit-shuffling function'
    a bit more closely.

    I find the phrase more than a bit confusing.
    Can you provide a good definition?
    It suggest that a function shuffles bits.
    But what exactly do you mean by that?

    Let's take a few examples.

    int zero0(void)
    return 0

    Is this a bit-shuffling function?
    If so, does it shuffle bits, and which bits does it shuffle?

    Let's take another example,

    #include <stdio.h>

    int zero1(void)
    FILE *hiddenlogfile = fopen("/hidden/zero.log", "a");
    if (hiddenlogfile)
    fputs("called zero()\n", hiddenlogfile);
    return 0;

    To the caller, the visible behaviour is the same as the behaviour of zero0,
    but zero1 does I/O: it writes a log message to a hidden log file.
    Is zero1 a bit-shuffling function?
    If not, which bits were not shuffled in zero1 that were shuffled in zero0?

    Another example:

    #include <stdlib.h>

    int zero2(void)
    system("sleep 999");
    return 0;

    The visible behaviour to the caller is the same as the behaviour
    of zero0, there is a side effect (a noticable delay), but let's assume
    there's no I/O done.

    Is zero2 a bit-shuffling function?
    How do the bits that were shuffled in zero2 (if any) differ from the bits
    that were shuffled in zero0 or zero1?

    And the last example,

    static int global = 0;

    int zero3(void)
    return 0;

    It has a side effect (it increments 'global') but does not do I/O;
    is zero3 a bit-shuffling function? If so, can you point out which
    bits it shuffled that were not shuffled in the other functions?
    Ike Naar, May 29, 2014
  11. James Harris

    Jorgen Grahn Guest

    Apparently. Mr McLean: please stop -- it's confusing, no matter what
    the theoretical merits of those terms are!

    Jorgen Grahn, May 29, 2014
  12. James Harris

    Jorgen Grahn Guest

    The latter. I don't think you should call what you're doing
    "exceptions" since that tends to imply:
    - placing exception handling at different places in the call chain
    - freeing of resources during stack unwinding
    Have you considered just calling abort()? If you're not going to
    continue anyway (your program would be in a rather weird state at this
    point) then aborting would give much more information for debugging
    than just function and line.

    Jorgen Grahn, May 29, 2014
  13. James Harris

    James Harris Guest

    "The latter"?
    Can do that.
    Can do that too!
    Thanks, no, I hadn't considered calling abort() ... for at least three

    1. I didn't know about it.
    2. I have a simple, if verbose, way to do what I want to do.
    3. This is for bare-metal code. There is no C run-time module, no OS, no
    signalling, etc.

    James Harris, May 29, 2014
  14. Stack overflow is a case of out of memory, however since you know stack usage for
    a non-recursive function, its normally doesn't need to be considered.
    You do have to assume that the computer is working.
    It's function which, given an input state of bits in the valid address space owned by the program,
    produces anther known output state of those bits, totally defined by the input state.
    (Of course in reality you only need consider a small subset of the bits, for most functions).
    The bits are in one state on function entry, another state on function exit, and the function
    can be replaced by any other function which produces the same bit state on output given
    the same bit state on input, without affecting the correctness of the program.
    If we assign the value, it
    x = zero();
    it shuffles x. given all 2^32 possible bit states of x on function entry, there's only one possible state
    on function exit.
    if we don't assign the value, it's a null shuffle. it's the function which maps input to output.
    It's affected the sate of something outside the program. If we replace it by the first function, the
    bit state is the same, but the program is no longer correct (assuming that part of the desired
    behaviour is to produce the log file).
    sleep is an exception which doesn't fit nicely in the system. You assume that results are important,
    an execution time isn't part of the behaviour. In reality, all programs have some limits on
    execution time.
    The don't. IO procedures also shuffle bits. But they have side effects as well.
    it's shuffled "global". That's why a "but shuffling function" isn't quite the same thing as a
    "pure function". Part of the behaviour is to increment global, so presumably it has
    partner functions which read global.

    What's the point?

    Bit shuffling functions.

    Are inherently portable. They run on any platform with enough memory.
    Are independently testable - they can be tested an proved correct independent of the status
    of and hardware devices attached to the machine.
    Can be idempotent - the can always be rewritten to avoid calls to other routines, with the
    sole exception of memory allocation.
    Have defined behaviour, assuming only that the computer is reliable.
    Malcolm McLean, May 29, 2014
  15. Im trying out "bit-shuffling function" and "IO procedure". That should strike the right balance
    between inventing incomprehensible jargon and using terms which are used in other
    Malcolm McLean, May 29, 2014
  16. Why not call them "bit-shuffling functions" and "IO functions", since C
    calls all subroutines "functions"?
    Keith Thompson, May 29, 2014
  17. Because the analysis isn't tied to C, though it's designed for C-like languages which
    operate on memory buffers.
    And because "function" in normal usage means "a mapping of an input set to an
    output set", or, in discrete digital terms, bit_shuffling, and "procedure" means
    "a series of actions or steps in a set protocol". We don't want to get too far from
    normal English usage by talking of "a function that sets the LED to flashing red".
    Malcolm McLean, May 29, 2014
  18. Perhaps comp.lang.misc would be a better place to discuss it.
    In comp.lang.c, "function" means "C function".

    If you find that the terminology used by the C standard (and by
    C programmers) is not suited to what you're discussing, then I
    suggest that what you're discussing is not suited to this newsgroup.

    Or perhaps you can reframe your ideas so they're specifically
    relevant to C.
    Keith Thompson, May 29, 2014
  19. Maybe. The idea of IO versus non-IO isn't in any way C-specific. However some
    of implications are better discussed with a concrete language in mind.
    A little thing like the fact that C uses "function" to mean "subroutine"
    shouldn't be hard for anyone to cope with.
    It's relevant to C because C makes it very obvious that you're bit-shuffling.
    Because C makes it easy to access the actual binary bits, it's clear how a
    C function can be rewritten in terms of shuffling rather than higher-level
    Also because C makes asking for memory explicit. It's obvious that a
    correctly-specified and written and called bit shuffling function can only
    fail if it runs out of memory. If it's passed an arrangement of bits it can't
    deal with (e.g. wild pointers), it's a programming error by caller, if it
    executes an illegal operation on a valid input bitset, it's an internal
    programming error. But it can always run out of memory, that's a sort of
    inherent problem in specifying a function in terms of expected output state
    given an input state. In C, it's obvious what's happened, because malloc()
    returns null. In other languages, the same underlying problem will happen,
    but it's harder for the programmer to see.
    Then the whole idea is ago separate out the bit-shuffling functions for the
    IO procedures. C makes that easy. If you don't include stdio.h or any third party
    IO-headers, you're bit shuffling. And since bit-shufling functions can be
    idempotent, normally you won't need any third party headers anyway, So
    you can see at a glance that the method has been applied.
    With other languages, you might have to specify 'serialise" interfaces or
    similar to basic classes. Whilst the idea still holds, it can become tricker and
    less intuitive.
    Malcolm McLean, May 29, 2014
  20. Yes, that's my point. If you think that statement makes your case for
    you, you'll have to elaborate; I'd say it argues precisely against what
    you're saying.
    Frankly, it seems to be difficult for you to cope with. Emphasis on
    "seems"; I don't really think you have difficulty understanding the
    concept. You just don't put it into practice.

    We have a perfectly good word, "function", with an *extremely* well
    defined meaning in this context. Feel free to add meaningful
    adjectives to it.

    Keith Thompson, May 29, 2014
    1. Advertisements

Ask a Question

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

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