How to resolve the algorithm Exceptions/Catch an exception thrown in a nested call step by step in the C programming language
How to resolve the algorithm Exceptions/Catch an exception thrown in a nested call step by step in the C programming language
Table of Contents
Problem Statement
Show how to create a user-defined exception and show how to catch an exception raised from several nested calls away.
Show/describe what happens when the program is run.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Exceptions/Catch an exception thrown in a nested call step by step in the C programming language
The goal of this code is to demonstrate portable exception handling using a custom exception context within functions and across function calls, simulating how exceptions would be managed in a complete application. Let's break down the code step by step:
-
Custom Exception Structure (
exception
):- This structure represents an exception with two fields:
extype
: An integer representing the type of exception.what
: A character array to store the error message.
- This structure represents an exception with two fields:
-
Exception Context Structure (
exception_ctx
):- This structure is used to manage a collection of exceptions. It contains:
exs
: An array ofexception
structures.size
: The size of theexs
array.pos
: The current position in theexs
array, indicating the last exception added.
- This structure is used to manage a collection of exceptions. It contains:
-
Exception Context Management Functions:
Create_Ex_Ctx(int length)
: Allocates memory and initializes anexception_ctx
structure with the specifiedlength
for theexs
array.Free_Ex_Ctx(exception_ctx * ctx)
: Deallocates the memory associated with the exception context.
-
Exception Handling Functions:
Has_Ex(exception_ctx * ctx)
: Checks if there is at least one exception in the context.Is_Ex_Type(exception_ctx * exctx, int extype)
: Checks if the last exception in the context matches the specifiedextype
.Pop_Ex(exception_ctx * ctx)
: Removes the last exception from the context.Get_What(exception_ctx * ctx)
: Returns the error message of the last exception.Push_Ex(exception_ctx * exctx, int extype, const char * msg)
: Adds a new exception to the context, setting itsextype
andwhat
fields.
-
Global Exception Context:
exception_ctx * GLOBALEX = NULL;
: Declares a globalexception_ctx
pointer namedGLOBALEX
that will be used throughout the program. This simulates a thread-local storage mechanism for exception handling.
-
Custom Exception Types:
enum { U0_DRINK_ERROR = 10, U1_ANGRYBARTENDER_ERROR };
: Declares two custom exception types,U0_DRINK_ERROR
andU1_ANGRYBARTENDER_ERROR
.
-
Function
baz(int n)
:- Depending on the value of
n
, this function demonstrates adding exceptions to the globalGLOBALEX
context:- If
n
is 0, it adds an exception of typeU0_DRINK_ERROR
. - Otherwise, it adds an exception of type
U1_ANGRYBARTENDER_ERROR
.
- If
- Depending on the value of
-
Function
bar(int n)
:- Calls
baz(n)
to potentially throw exceptions. - Checks if there are exceptions in the context using
Has_Ex
. - Handles exceptions of type
U0_DRINK_ERROR
by printing a message to the standard error output and popping the exception. - If any other exceptions are present, the function returns early.
- Calls
-
Function
foo()
:- This function simulates a loop where exceptions can be thrown and handled repeatedly.
- It calls
bar(0)
and handles anyU0_DRINK_ERROR
exceptions. - Then, it calls
bar(1)
and continues handlingU0_DRINK_ERROR
exceptions.
-
Function
main()
:
- Creates an exception context with a size of 5.
- Sets the
GLOBALEX
pointer to this context, simulating a thread-specific exception context. - Calls
foo()
. - Checks for any remaining exceptions in the context and prints their error messages.
- Deallocates the exception context.
In summary, this code demonstrates how to create a custom exception handling mechanism using a stack-based exception context. It simulates how errors can be raised and handled within functions and across function calls, centralizing the error handling logic and providing a structured way to deal with exceptions.
Source code in the c programming language
#include <stdio.h>
#include <stdlib.h>
typedef struct exception {
int extype;
char what[128];
} exception;
typedef struct exception_ctx {
exception * exs;
int size;
int pos;
} exception_ctx;
exception_ctx * Create_Ex_Ctx(int length) {
const int safety = 8; // alignment precaution.
char * tmp = (char*) malloc(safety+sizeof(exception_ctx)+sizeof(exception)*length);
if (! tmp) return NULL;
exception_ctx * ctx = (exception_ctx*)tmp;
ctx->size = length;
ctx->pos = -1;
ctx->exs = (exception*) (tmp + sizeof(exception_ctx));
return ctx;
}
void Free_Ex_Ctx(exception_ctx * ctx) {
free(ctx);
}
int Has_Ex(exception_ctx * ctx) {
return (ctx->pos >= 0) ? 1 : 0;
}
int Is_Ex_Type(exception_ctx * exctx, int extype) {
return (exctx->pos >= 0 && exctx->exs[exctx->pos].extype == extype) ? 1 : 0;
}
void Pop_Ex(exception_ctx * ctx) {
if (ctx->pos >= 0) --ctx->pos;
}
const char * Get_What(exception_ctx * ctx) {
if (ctx->pos >= 0) return ctx->exs[ctx->pos].what;
return NULL;
}
int Push_Ex(exception_ctx * exctx, int extype, const char * msg) {
if (++exctx->pos == exctx->size) {
// Use last slot and report error.
--exctx->pos;
fprintf(stderr, "*** Error: Overflow in exception context.\n");
}
snprintf(exctx->exs[exctx->pos].what, sizeof(exctx->exs[0].what), "%s", msg);
exctx->exs[exctx->pos].extype = extype;
return -1;
}
//////////////////////////////////////////////////////////////////////
exception_ctx * GLOBALEX = NULL;
enum { U0_DRINK_ERROR = 10, U1_ANGRYBARTENDER_ERROR };
void baz(int n) {
if (! n) {
Push_Ex(GLOBALEX, U0_DRINK_ERROR , "U0 Drink Error. Insufficient drinks in bar Baz.");
return;
}
else {
Push_Ex(GLOBALEX, U1_ANGRYBARTENDER_ERROR , "U1 Bartender Error. Bartender kicked customer out of bar Baz.");
return;
}
}
void bar(int n) {
fprintf(stdout, "Bar door is open.\n");
baz(n);
if (Has_Ex(GLOBALEX)) goto bar_cleanup;
fprintf(stdout, "Baz has been called without errors.\n");
bar_cleanup:
fprintf(stdout, "Bar door is closed.\n");
}
void foo() {
fprintf(stdout, "Foo entering bar.\n");
bar(0);
while (Is_Ex_Type(GLOBALEX, U0_DRINK_ERROR)) {
fprintf(stderr, "I am foo() and I deaall wrth U0 DriNk Errors with my own bottle... GOT oNE! [%s]\n", Get_What(GLOBALEX));
Pop_Ex(GLOBALEX);
}
if (Has_Ex(GLOBALEX)) return;
fprintf(stdout, "Foo left the bar.\n");
fprintf(stdout, "Foo entering bar again.\n");
bar(1);
while (Is_Ex_Type(GLOBALEX, U0_DRINK_ERROR)) {
fprintf(stderr, "I am foo() and I deaall wrth U0 DriNk Errors with my own bottle... GOT oNE! [%s]\n", Get_What(GLOBALEX));
Pop_Ex(GLOBALEX);
}
if (Has_Ex(GLOBALEX)) return;
fprintf(stdout, "Foo left the bar.\n");
}
int main(int argc, char ** argv) {
exception_ctx * ctx = Create_Ex_Ctx(5);
GLOBALEX = ctx;
foo();
if (Has_Ex(ctx)) goto main_ex;
fprintf(stdout, "No errors encountered.\n");
main_ex:
while (Has_Ex(ctx)) {
fprintf(stderr, "*** Error: %s\n", Get_What(ctx));
Pop_Ex(ctx);
}
Free_Ex_Ctx(ctx);
return 0;
}
You may also check:How to resolve the algorithm Append a record to the end of a text file step by step in the Mathematica / Wolfram Language programming language
You may also check:How to resolve the algorithm Range expansion step by step in the Elixir programming language
You may also check:How to resolve the algorithm Flow-control structures step by step in the REXX programming language
You may also check:How to resolve the algorithm Short-circuit evaluation step by step in the Haskell programming language
You may also check:How to resolve the algorithm Get system command output step by step in the Objeck programming language