HiveBrain v1.2.0
Get Started
← Back to all entries
debugcMinor

A closed exception system

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
systemclosedexception

Problem

I am working on yet another toy project that I named SGL (for "Standard Generic Library" since it mimics some features of C++'s STL as well as a few more utilities from the C++ standard library). Since the library is not meant to be used in real code, I decided that I would have fun and tried to implement a setjmp/longjmp-based exception mechanism.

First, the code. You'll have some rationale, explanation and design decisions later.

sgl/exception.h

```
#ifndef SGL_EXCEPTION_H_
#define SGL_EXCEPTION_H_

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include
#include
#include
#include

////////////////////////////////////////////////////////////
// Exceptions

/**
* @brief Basic exception type.
*
* The exceptions must be integers to satisfy the longjmp
* function. The names used here are those of the exceptions
* defined in the C++ header and some other ones
* from the C++ standard library. The mechanism cannot be
* extended with user-defined types.
*
* The default sgl_exception is not meant to be thrown nor printed.
* It only exists so that it can be used to catch any exception in
* a catch block.
*/
typedef enum
{
sgl_exception = -1,
sgl_logic_error,
sgl_domain_error,
sgl_invalid_argument,
sgl_length_error,
sgl_out_of_range,
sgl_runtime_error,
sgl_range_error,
sgl_overflow_error,
sgl_underflow_error,
sgl_bad_alloc,
sgl_detail_exceptions_number
} sgl_exception_t;

#ifndef SGL_MAX_EXCEPTIONS

/**
* @def SGL_MAX_EXCEPTIONS
*
* Maximum number of nested exception blocks allowed in SGL.
* It can be set to N with the compiler option
* -DSGL_MAX_EXCEPTIONS=N
*/
#define SGL_MAX_EXCEPTIONS 32

#endif

////////////////////////////////////////////////////////////
// Global implementation variables

// Global array of jmp_buf
extern jmp_buf sgl_detail_buf_array[SGL_MAX_EXCEPTIONS];

//

Solution

Some small stuff:

sgl_detail_current_exception is initialize to 0 as it is in global memory. Given the enumerated list starts with -1, then sgl_logic_error == 0:

sgl_exception_t sgl_detail_current_exception;
// is effectively 
sgl_exception_t sgl_detail_current_exception = sgl_logic_error;


Recommend adding an enumerated value of sgl_none = 0 to distinguish the initial state and explicitly initialize sgl_detail_current_exception.

typedef enum
{
    sgl_exception = -1,
    sgl_none = 0,
    sgl_logic_error,
    sgl_domain_error,
    ...

sgl_exception_t sgl_detail_current_exception = sgl_none;


Rather than messages[], use messages[sgl_detail_exceptions_number] as that array size must be a matching value. This will help should only one of messages[] or sgl_exception_t errantly change. Similar for inheritance[].

Potential inconsistencies with sgl_detail_exceptions_number not limited to 15, uint_fast16_t, int range may be as small as -32767 to 32767. Suggest:

assert(sgl_detail_exceptions_number < 16);

// use const
static const uint_fast16_t inheritance[] = {
    1u << sgl_logic_error,   // add 'u' here and many other places
    ...


Did not notice any limit in code to incrementing sgl_detail_exceptions_index. suggest adding test to insure sgl_detail_exceptions_index < SGL_MAX_EXCEPTIONS before access arrays.

#define sgl_try                                                             \
    do {                                                                    \
        ++sgl_detail_exceptions_index;                                      \
        //  Hmmm: out of bounds potential
        sgl_detail_in_catch_bloc[sgl_detail_exceptions_index] = false;      \

Code Snippets

sgl_exception_t sgl_detail_current_exception;
// is effectively 
sgl_exception_t sgl_detail_current_exception = sgl_logic_error;
typedef enum
{
    sgl_exception = -1,
    sgl_none = 0,
    sgl_logic_error,
    sgl_domain_error,
    ...

sgl_exception_t sgl_detail_current_exception = sgl_none;
assert(sgl_detail_exceptions_number < 16);

// use const
static const uint_fast16_t inheritance[] = {
    1u << sgl_logic_error,   // add 'u' here and many other places
    ...
#define sgl_try                                                             \
    do {                                                                    \
        ++sgl_detail_exceptions_index;                                      \
        //  Hmmm: out of bounds potential
        sgl_detail_in_catch_bloc[sgl_detail_exceptions_index] = false;      \

Context

StackExchange Code Review Q#95195, answer score: 7

Revisions (0)

No revisions yet.