debugcMinor
A closed exception system
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
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];
//
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:
Recommend adding an enumerated value of
Rather than
Potential inconsistencies with
Did not notice any limit in code to incrementing
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.