469,613 Members | 1,267 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,613 developers. It's quick & easy.

Need experts opnion

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 '06 #1
18 1260
va******@rediffmail.com 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.

Jan 5 '06 #2

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 '06 #3
va******@rediffmail.com 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/>
Jan 5 '06 #4

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 '06 #5

va******@rediffmail.com 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.

Jan 5 '06 #6
va******@rediffmail.com 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.
Jan 5 '06 #7
In article <11**********************@g44g2000cwa.googlegroups .com>,
va******@rediffmail.com 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.
Jan 5 '06 #8
Christian Bau wrote:
In article <11**********************@g44g2000cwa.googlegroups .com>,
va******@rediffmail.com 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;
}

Jan 6 '06 #9
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/>
Jan 6 '06 #10
Christian Bau wrote:
In article <11**********************@g44g2000cwa.googlegroups .com>,
va******@rediffmail.com 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
es*****@acm-dot-org.invalid
Jan 6 '06 #11
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 7 '06 #12
In article <11*********************@g14g2000cwa.googlegroups. com>,
va******@rediffmail.com 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.
Jan 7 '06 #13
>
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.

Jan 7 '06 #14
va******@rediffmail.com 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/>
Jan 7 '06 #15
In article <11**********************@g49g2000cwa.googlegroups .com>
tmp123 <tm****@menta.net> 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.
Jan 7 '06 #16
"tmp123" <tm****@menta.net> 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
Jan 9 '06 #17

Richard Bos wrote:
"tmp123" <tm****@menta.net> 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?

Jan 10 '06 #18
"tmp123" <tm****@menta.net> wrote:
Richard Bos wrote:
"tmp123" <tm****@menta.net> 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
Jan 10 '06 #19

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.