Need experts opnion

Discussion in 'C Programming' started by vashwath@rediffmail.com, Jan 5, 2006.

  1. Guest

    Hi all,
    In my current project I am thinking to use setjmp/lngjmp for exception
    handling.The way I am planing to do this is shown in the below example.
    Please if this is the right way to do.Are there any disadvantages in
    this method?

    #include <stdio.h>
    #include <setjmp.h>
    #include <stdlib.h>
    jmp_buf g_env;
    extern void fun1();
    int main()
    {
    int ret;

    ret = setjmp(g_env);
    if (ret == 0)
    {
    printf("Perform the intended functionality");
    fun1();
    exit(EXIT_SUCCESS);
    }
    else
    {
    printf("Exception handling\n");
    exit(EXIT_FAILURE);
    }

    }


    #include <stdio.h>
    #include <setjmp.h>

    extern jmp_buf g_env;

    void fun1()
    {
    longjmp(g_env,1);
    }
     
    , Jan 5, 2006
    #1
    1. Advertising

  2. tmp123 Guest

    wrote:
    > Hi all,
    > In my current project I am thinking to use setjmp/lngjmp for exception
    > handling.The way I am planing to do this is shown in the below example.
    > Please if this is the right way to do.Are there any disadvantages in
    > this method?
    >
    > #include <stdio.h>
    > #include <setjmp.h>
    > #include <stdlib.h>
    > jmp_buf g_env;
    > extern void fun1();
    > int main()
    > {
    > int ret;
    >
    > ret = setjmp(g_env);
    > if (ret == 0)
    > {
    > printf("Perform the intended functionality");
    > fun1();
    > exit(EXIT_SUCCESS);
    > }
    > else
    > {
    > printf("Exception handling\n");
    > exit(EXIT_FAILURE);
    > }
    >
    > }
    >
    >
    > #include <stdio.h>
    > #include <setjmp.h>
    >
    > extern jmp_buf g_env;
    >
    > void fun1()
    > {
    > longjmp(g_env,1);
    > }




    Hi,

    Starting with the code you has post, there are several posible
    improvements:

    1) Do not use a single jmp_buf, but an array of it.
    2) Define macros to made more visible the exception handling. Only as
    an example:

    #define TRY if (setjmp(g_env))
    #define CATCH else
    #define THROW(x) longjmp(g_env,x)

    mades the code

    TRY
    {
    }
    CATCH
    {
    }

    ....


    THROW(1)

    3) Do not forget the falg volatile when necessary.

    Kind regards.
     
    tmp123, Jan 5, 2006
    #2
    1. Advertising

  3. Guest

    tmp123 wrote:
    > 1) Do not use a single jmp_buf, but an array of it.


    Could you please explain in detail why jmp_buf should be an array?
     
    , Jan 5, 2006
    #3
  4. Chuck F. Guest

    wrote:
    >
    > In my current project I am thinking to use setjmp/lngjmp for
    > exception handling.The way I am planing to do this is shown in
    > the below example. Please if this is the right way to do.Are
    > there any disadvantages in this method?
    >

    *** quote munged to reduce vertical space ***
    > #include <stdio.h>
    > #include <setjmp.h>
    > #include <stdlib.h>
    > jmp_buf g_env;
    > extern void fun1();
    > int main()
    > {
    > int ret;
    >
    > ret = setjmp(g_env);
    > if (ret == 0) {
    > printf("Perform the intended functionality");
    > fun1();
    > exit(EXIT_SUCCESS);
    > }
    > else {
    > printf("Exception handling\n");
    > exit(EXIT_FAILURE);
    > }
    > }
    >
    > #include <stdio.h>
    > #include <setjmp.h>
    >
    > extern jmp_buf g_env;
    >
    > void fun1()
    > {
    > longjmp(g_env,1);
    > }


    Surprise. Your very first statement "ret = setjmp(...)" is
    illegal! The following is a quote from N869:

    Environmental limits

    [#4] An invocation of the setjmp macro shall appear only in
    one of the following contexts:

    -- the entire controlling expression of a selection or
    iteration statement;

    -- one operand of a relational or equality operator with
    the other operand an integer constant expression, with
    the resulting expression being the entire controlling
    expression of a selection or iteration statement;

    -- the operand of a unary ! operator with the resulting
    expression being the entire controlling expression of a
    selection or iteration statement; or

    -- the entire expression of an expression statement
    (possibly cast to void).

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
     
    Chuck F., Jan 5, 2006
    #4
  5. Guest

    Chuck F. wrote:
    > Surprise. Your very first statement "ret = setjmp(...)" is
    > illegal! The following is a quote from N869:
    >
    > Environmental limits
    >
    > [#4] An invocation of the setjmp macro shall appear only in
    > one of the following contexts:
    >
    > -- the entire controlling expression of a selection or
    > iteration statement;
    >
    > -- one operand of a relational or equality operator with
    > the other operand an integer constant expression, with
    > the resulting expression being the entire controlling
    > expression of a selection or iteration statement;
    >
    > -- the operand of a unary ! operator with the resulting
    > expression being the entire controlling expression of a
    > selection or iteration statement; or
    >
    > -- the entire expression of an expression statement
    > (possibly cast to void).

    I am not able to understand any of these points. Can anybody explain in
    simpler way(if possible with an example)?
    Thanks in Advance
     
    , Jan 5, 2006
    #5
  6. tmp123 Guest

    wrote:
    > tmp123 wrote:
    > > 1) Do not use a single jmp_buf, but an array of it.

    >
    > Could you please explain in detail why jmp_buf should be an array?


    If you have an array of similar, you can have nested TRYs, in same or
    different procedures.

    Kind regards.
     
    tmp123, Jan 5, 2006
    #6
  7. Flash Gordon Guest

    wrote:
    > Chuck F. wrote:
    >> Surprise. Your very first statement "ret = setjmp(...)" is
    >> illegal! The following is a quote from N869:
    >>
    >> Environmental limits
    >>
    >> [#4] An invocation of the setjmp macro shall appear only in
    >> one of the following contexts:
    >>
    >> -- the entire controlling expression of a selection or
    >> iteration statement;
    >>
    >> -- one operand of a relational or equality operator with
    >> the other operand an integer constant expression, with
    >> the resulting expression being the entire controlling
    >> expression of a selection or iteration statement;
    >>
    >> -- the operand of a unary ! operator with the resulting
    >> expression being the entire controlling expression of a
    >> selection or iteration statement; or
    >>
    >> -- the entire expression of an expression statement
    >> (possibly cast to void).

    > I am not able to understand any of these points. Can anybody explain in
    > simpler way(if possible with an example)?
    > Thanks in Advance


    You are not allowed to do something like
    ret = setjmp(...);
    You should do something like:
    if (setjmp(...)...)
    or:
    if (!setjmp(...))
    or:
    switch (setjmp(...)) {
    ...
    }
    You can also just have a line:
    setjmp(...);
    I.e. not using the value returned.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Jan 5, 2006
    #7
  8. In article <>,
    wrote:

    > Hi all,
    > In my current project I am thinking to use setjmp/lngjmp for exception
    > handling.The way I am planing to do this is shown in the below example.
    > Please if this is the right way to do.Are there any disadvantages in
    > this method?


    One problem with any kind of exception handling is that exceptions
    thrown will return to the exception handling code, skipping all function
    calls in between. Any cleanup that is required by functions between the
    initial caller and the place where the exception is thrown will not be
    executed.

    In Java, this problem is partially solved by having garbage collection.
    Just organise your code so that throwing away dynamically allocated
    objects will be enough to clean up. In C++, this problem is partially
    solved by having destructors. Just organise your code so that
    destructing any objects on the stack will be enough to clean up. In C,
    there is no such thing. Any cleanup has to be done manually. You will
    find yourself in major trouble very soon.

    Unless you want to put superhuman effort into exception handling, the
    only thing you can do in C is using setjmp/longjmp to cover complete
    major subsystems; allocating all memory through functions that keep
    track of allocation and free all memory when an exception happens,
    installing function pointers for cleanup when necessary. This is a major
    operation that needs experienced and diligent programmers.
     
    Christian Bau, Jan 5, 2006
    #8
  9. Guest


    > In Java, this problem is partially solved by having garbage collection.
    > Just organise your code so that throwing away dynamically allocated
    > objects will be enough to clean up.


    If I intialize all the pointers used for allocating memory to NULL and
    call free on all these pointers uppon exception, then I have cleaned up
    successfully is'nt it?
     
    , Jan 6, 2006
    #9
  10. tmp123 Guest

    Christian Bau wrote:
    > In article <>,
    > wrote:
    >
    > > Hi all,
    > > In my current project I am thinking to use setjmp/lngjmp for exception
    > > handling.The way I am planing to do this is shown in the below example.
    > > Please if this is the right way to do.Are there any disadvantages in
    > > this method?

    >
    > One problem with any kind of exception handling is that exceptions
    > thrown will return to the exception handling code, skipping all function
    > calls in between. Any cleanup that is required by functions between the
    > initial caller and the place where the exception is thrown will not be
    > executed.
    >
    > In Java, this problem is partially solved by having garbage collection.
    > Just organise your code so that throwing away dynamically allocated
    > objects will be enough to clean up. In C++, this problem is partially
    > solved by having destructors. Just organise your code so that
    > destructing any objects on the stack will be enough to clean up. In C,
    > there is no such thing. Any cleanup has to be done manually. You will
    > find yourself in major trouble very soon.
    >
    > Unless you want to put superhuman effort into exception handling, the
    > only thing you can do in C is using setjmp/longjmp to cover complete
    > major subsystems; allocating all memory through functions that keep
    > track of allocation and free all memory when an exception happens,
    > installing function pointers for cleanup when necessary. This is a major
    > operation that needs experienced and diligent programmers.



    I agree on the previous (the reference to Java memory handling could be
    completed with some security issues? and nested tries must be
    referenced?).

    However, the advantages of exceptions are also important. (Well, in
    fact, nobody doubts today about benefits of exceptions, so, I'm being
    redundant)

    See two examples of a usual code with an without:

    char * getLine( void )
    {
    FILE *f=NULL;
    char *r=NULL;

    if ( (r=malloc_string() == NULL ) return NULL;
    if ( (f=file_open() == NULL )
    {
    /* Mixed messages and code!*/
    fprintf(stderr, "unable to alloc...);
    free(r);
    return NULL;
    }
    if ( fgets(...) ... )
    {
    fprintf(stderr, "unable to ...);
    free(r);
    fclose(f); /* error handling grows! */
    return NULL;
    }
    ...
    fclose(f);
    return r;
    }

    char * getLines( const char *name )
    {
    FILE *f=NULL;
    char *r=NULL;

    TRY
    {
    f=file_open();
    r=malloc_string();
    if ( fgets(...) ... ) THROW(EXC_FAIL_READ);
    ...
    fclose(f);
    }
    CATCH
    {
    if ( f != NULL ) fclose(f);
    if ( r != NULL ) free(r);
    r = NULL;
    /* write errro messages or keep it in the main TRY */
    THROW_NEXT;
    }
    END_TRY
    return r;
    }
     
    tmp123, Jan 6, 2006
    #10
  11. Chuck F. Guest

    tmp123 wrote:
    >

    .... snip ...
    >
    > However, the advantages of exceptions are also important. (Well,
    > in fact, nobody doubts today about benefits of exceptions, so,
    > I'm being redundant)
    >
    > See two examples of a usual code with an without:
    >
    > char * getLine( void )
    > {
    > FILE *f=NULL;
    > char *r=NULL;
    >
    > if ( (r=malloc_string() == NULL ) return NULL;
    > if ( (f=file_open() == NULL )
    > {
    > /* Mixed messages and code!*/
    > fprintf(stderr, "unable to alloc...);
    > free(r);
    > return NULL;
    > }
    > if ( fgets(...) ... )
    > {
    > fprintf(stderr, "unable to ...);
    > free(r);
    > fclose(f); /* error handling grows! */
    > return NULL;
    > }
    > ...
    > fclose(f);
    > return r;
    > }


    Here is my rewrite of that:

    char * getLine(void)
    {
    FILE *f = NULL;
    char *r, *rv = NULL;

    if (!(r = mallocstring())) fprintf(stderr, "alloc..");
    else if (!(f = file_open()) fprintf(stderr, "file ..");
    else if (!fgets(...)) fprintf(stderr, "read ...");
    else {
    rv = r;
    ....
    }
    if (!rv) free(r);
    if (f) fclose(f);
    return rv;
    }

    (which I believe has the identical function, and has a single point
    of return.) In practice I would probably postpone the malloc until
    I had determined that the file would open.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
     
    Chuck F., Jan 6, 2006
    #11
  12. Eric Sosman Guest

    Christian Bau wrote:

    > In article <>,
    > wrote:
    >
    >
    >>Hi all,
    >>In my current project I am thinking to use setjmp/lngjmp for exception
    >>handling.The way I am planing to do this is shown in the below example.
    >>Please if this is the right way to do.Are there any disadvantages in
    >>this method?

    >
    >
    > One problem with any kind of exception handling is that exceptions
    > thrown will return to the exception handling code, skipping all function
    > calls in between. Any cleanup that is required by functions between the
    > initial caller and the place where the exception is thrown will not be
    > executed.
    >
    > In Java, this problem is partially solved by having garbage collection.
    > [...]


    And more thoroughly solved by the try/finally construct.
    The lack of something analogous is what makes exception-like
    constructs in "plain C" vulnerable to the problem you describe.
    Solving the problem in "plain C" isn't impossible, but involves
    more than simply calling setjmp() and longjmp() -- for example,
    you'll need to be able to form chains of contexts so an exception
    thrown in f() can cause cleanup actions in e() and d() and c()
    and b() before being caught in a(). The machinery to manage the
    context chains needn't be elaborate, but must be carefully crafted.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jan 6, 2006
    #12
  13. In article <>,
    wrote:

    > > In Java, this problem is partially solved by having garbage collection.
    > > Just organise your code so that throwing away dynamically allocated
    > > objects will be enough to clean up.

    >
    > If I intialize all the pointers used for allocating memory to NULL and
    > call free on all these pointers uppon exception, then I have cleaned up
    > successfully is'nt it?


    But how do you do this? (Code is just for illustration, no guarantee
    that it compiles or works)

    void function_throwing_exception ()
    {
    longjmp (jmpbuf, 1);
    }

    void function_in_the_middle ()
    {
    char* p = NULL;
    char* q = NULL;
    char* r = NULL;

    p = malloc (100);
    q = malloc (100);
    r = malloc (100);
    function_throwing_exception ();
    free (r);
    free (q);
    free (p);
    }

    void caller ()
    {
    jmp_buf jmpbuf;
    if (setjmp (jmpbuf))
    {
    function_in_the_middle ();
    }
    }

    Now tell me how you clean up p, q and r when the exception is thrown.
     
    Christian Bau, Jan 7, 2006
    #13
  14. tmp123 Guest

    >
    > But how do you do this? (Code is just for illustration, no guarantee
    > that it compiles or works)
    >
    > void function_throwing_exception ()
    > {
    > longjmp (jmpbuf, 1);
    > }
    >
    > void function_in_the_middle ()
    > {
    > char* p = NULL;
    > char* q = NULL;
    > char* r = NULL;
    >
    > p = malloc (100);
    > q = malloc (100);
    > r = malloc (100);
    > function_throwing_exception ();
    > free (r);
    > free (q);
    > free (p);
    > }
    >
    > void caller ()
    > {
    > jmp_buf jmpbuf;
    > if (setjmp (jmpbuf))
    > {
    > function_in_the_middle ();
    > }
    > }
    >
    > Now tell me how you clean up p, q and r when the exception is thrown.


    As some others person have said, nested TRYs. Nothing new, same than in
    C++ and others. Something more or less like:

    void function_throwing_exception ()
    {
    THROW(1);
    }

    void function_in_the_middle ()
    {
    char* p = NULL;
    char* q = NULL;
    char* r = NULL;

    TRY
    {
    p = malloc (100);
    q = malloc (100);
    r = malloc (100);
    function_throwing_exception ();
    free (r);
    free (q);
    free (p);
    }
    CATCH
    {
    free (r);
    free (q);
    free (p);
    THROW_BACKWARD;
    }
    }

    void caller ()
    {
    TRY
    {
    function_in_the_middle ();
    }
    ...
    }

    My conclusion about this subject: use C++ compilers, even if the
    keyword "class" is not used, except if no available or other hard
    specification restrictions.
     
    tmp123, Jan 7, 2006
    #14
  15. Chuck F. Guest

    wrote:
    >
    >> In Java, this problem is partially solved by having garbage
    >> collection. Just organise your code so that throwing away
    >> dynamically allocated objects will be enough to clean up.

    >
    > If I intialize all the pointers used for allocating memory to
    > NULL and call free on all these pointers uppon exception, then I
    > have cleaned up successfully is'nt it?


    No. You also have to invert the order of allocation. Think of
    linked lists or trees.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
     
    Chuck F., Jan 7, 2006
    #15
  16. Chris Torek Guest

    In article <>
    tmp123 <> wrote:
    >My conclusion about this subject: use C++ compilers, even if the
    >keyword "class" is not used, except if no available or other hard
    >specification restrictions.


    And what happens when you use a C++ compiler on the following
    C program? (Note, it is stripped-down to make the problem more
    apparent. If the problem is not immediately obvious, compile it
    as both C and C++ and run both versions.)

    #include <stdio.h>

    struct A { char a[100]; };

    int main(int argc, char **argv) {
    struct B { struct A { char a; } b; } b;

    printf("sizeof(struct A) = %lu\n",
    (unsigned long)sizeof(struct A));
    return 0;
    }

    (Although this particular example is stripped-down and looks
    contrived, this was actually a real issue in a real program
    in which someone carelessly attempted to mix C and C++ code.)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jan 7, 2006
    #16
  17. Richard Bos Guest

    "tmp123" <> wrote:

    > void function_throwing_exception ()
    > {
    > THROW(1);
    > }
    >
    > void function_in_the_middle ()
    > {
    > char* p = NULL;
    > char* q = NULL;
    > char* r = NULL;
    >
    > TRY
    > {
    > p = malloc (100);
    > q = malloc (100);
    > r = malloc (100);
    > function_throwing_exception ();
    > free (r);
    > free (q);
    > free (p);
    > }
    > CATCH
    > {
    > free (r);
    > free (q);
    > free (p);
    > THROW_BACKWARD;
    > }
    > }
    >
    > void caller ()
    > {
    > TRY
    > {
    > function_in_the_middle ();
    > }
    > ...
    > }
    >
    > My conclusion about this subject: use C++ compilers, even if the
    > keyword "class" is not used, except if no available or other hard
    > specification restrictions.


    "Good" advice... since the code above does not compile under C++,
    because that language is broken-as-designed where void * is involved.

    Richard
     
    Richard Bos, Jan 9, 2006
    #17
  18. tmp123 Guest

    Richard Bos wrote:
    > "tmp123" <> wrote:
    >
    > > void function_throwing_exception ()
    > > {
    > > THROW(1);
    > > }
    > >
    > > void function_in_the_middle ()
    > > {
    > > char* p = NULL;
    > > char* q = NULL;
    > > char* r = NULL;
    > >
    > > TRY
    > > {
    > > p = malloc (100);
    > > q = malloc (100);
    > > r = malloc (100);
    > > function_throwing_exception ();
    > > free (r);
    > > free (q);
    > > free (p);
    > > }
    > > CATCH
    > > {
    > > free (r);
    > > free (q);
    > > free (p);
    > > THROW_BACKWARD;
    > > }
    > > }
    > >
    > > void caller ()
    > > {
    > > TRY
    > > {
    > > function_in_the_middle ();
    > > }
    > > ...
    > > }
    > >
    > > My conclusion about this subject: use C++ compilers, even if the
    > > keyword "class" is not used, except if no available or other hard
    > > specification restrictions.

    >
    > "Good" advice... since the code above does not compile under C++,
    > because that language is broken-as-designed where void * is involved.
    >
    > Richard


    Also "..." can cause problems, and the lack of definition for TRY, and
    others.
    It is somekind of joke?
     
    tmp123, Jan 10, 2006
    #18
  19. Richard Bos Guest

    "tmp123" <> wrote:

    > Richard Bos wrote:
    > > "tmp123" <> wrote:
    > >
    > > > void function_throwing_exception ()
    > > > {
    > > > THROW(1);
    > > > }
    > > >
    > > > void function_in_the_middle ()
    > > > {
    > > > char* p = NULL;
    > > > char* q = NULL;
    > > > char* r = NULL;
    > > >
    > > > TRY
    > > > {
    > > > p = malloc (100);
    > > > q = malloc (100);
    > > > r = malloc (100);
    > > > function_throwing_exception ();
    > > > free (r);
    > > > free (q);
    > > > free (p);
    > > > }
    > > > CATCH
    > > > {
    > > > free (r);
    > > > free (q);
    > > > free (p);
    > > > THROW_BACKWARD;
    > > > }
    > > > }
    > > >
    > > > void caller ()
    > > > {
    > > > TRY
    > > > {
    > > > function_in_the_middle ();
    > > > }
    > > > ...
    > > > }
    > > >
    > > > My conclusion about this subject: use C++ compilers, even if the
    > > > keyword "class" is not used, except if no available or other hard
    > > > specification restrictions.

    > >
    > > "Good" advice... since the code above does not compile under C++,
    > > because that language is broken-as-designed where void * is involved.

    >
    > Also "..." can cause problems, and the lack of definition for TRY, and
    > others.


    Those can be corrected with good C code. The point I refer to cannot.

    Richard
     
    Richard Bos, Jan 10, 2006
    #19
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. AW
    Replies:
    0
    Views:
    312
  2. samir dsf
    Replies:
    0
    Views:
    332
    samir dsf
    Jan 27, 2006
  3. Santa
    Replies:
    2
    Views:
    408
    Roedy Green
    Jan 8, 2004
  4. Gsec

    Need experts suggestion

    Gsec, May 26, 2006, in forum: C Programming
    Replies:
    68
    Views:
    1,103
    Malcolm
    Jun 10, 2006
  5. perry.yuan
    Replies:
    9
    Views:
    338
Loading...

Share This Page