How to resolve the algorithm Exceptions/Catch an exception thrown in a nested call step by step in the C programming language

Published on 7 June 2024 03:52 AM
#C

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:

  1. 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.
  2. Exception Context Structure (exception_ctx):

    • This structure is used to manage a collection of exceptions. It contains:
      • exs: An array of exception structures.
      • size: The size of the exs array.
      • pos: The current position in the exs array, indicating the last exception added.
  3. Exception Context Management Functions:

    • Create_Ex_Ctx(int length): Allocates memory and initializes an exception_ctx structure with the specified length for the exs array.
    • Free_Ex_Ctx(exception_ctx * ctx): Deallocates the memory associated with the exception context.
  4. 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 specified extype.
    • 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 its extype and what fields.
  5. Global Exception Context:

    • exception_ctx * GLOBALEX = NULL;: Declares a global exception_ctx pointer named GLOBALEX that will be used throughout the program. This simulates a thread-local storage mechanism for exception handling.
  6. Custom Exception Types:

    • enum { U0_DRINK_ERROR = 10, U1_ANGRYBARTENDER_ERROR };: Declares two custom exception types, U0_DRINK_ERROR and U1_ANGRYBARTENDER_ERROR.
  7. Function baz(int n):

    • Depending on the value of n, this function demonstrates adding exceptions to the global GLOBALEX context:
      • If n is 0, it adds an exception of type U0_DRINK_ERROR.
      • Otherwise, it adds an exception of type U1_ANGRYBARTENDER_ERROR.
  8. 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.
  9. Function foo():

    • This function simulates a loop where exceptions can be thrown and handled repeatedly.
    • It calls bar(0) and handles any U0_DRINK_ERROR exceptions.
    • Then, it calls bar(1) and continues handling U0_DRINK_ERROR exceptions.
  10. 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