You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@celix.apache.org by Alexander Broekhuis <a....@gmail.com> on 2011/02/13 13:36:24 UTC

Exception Handling in C

Hello everyone,

Now that everything is in SVN, I would like to start working on the code again.

There is one important aspect which still needs a solution: Exception handling
Celix follows the OSGi spec (Java), but since C doesn't have
exceptions like Java, a solution is needed to be able to report
errors/exceptions.

I've been looking on the web, and found 2 possible solutions.

1) Using a library that uses setjmp/longjmp:
Examples are:
- http://libexcept.sourceforge.net/
- http://www.nicemice.net/cexcept/
- http://code.google.com/p/exceptions4c/

2) Use the return value of functions:
- For example by simply returning a int value indicating the error
- Use a library which supplies try/catch macros: http://code.google.com/p/libex/

The first solution makes it possible to have an API very similar to
the OSGi spec, but I am not sure how setjmp and longjmp interact with
threads and real time behavior.
The second solution is the most simple, and with the help of a library
it is still possible to have clear code with try/catch constructs.

Does anyone have any experience with these kind of libraries?

For now I tend to lean towards using a simple solution, either simply
returning the error code, or using something like libex (which is
lgpl, which might be a problem..).

-- 
Kind regards,

Alexander Broekhuis

Re: Exception Handling in C

Posted by Alexander Broekhuis <a....@gmail.com>.
Hi Bob,

> Hello everyone,
>
> This is my first commit on this mailing list, so Ill briefly introduce
> myself: I'm Bob Fels, software engineer in embedded real time systems.
> For that I mainly use C, but I am also experienced in C++, Java, Python,
> Perl, various assembly flavors etc.
>
> I am every interested in using a service approach in embedded software,
> so Celix drew my interest.

Good to see you here!

>
> switch (my_function())
> {
>        case CELIX_RETURN_OK:
>                break;
>        case CELIX_RETURN_OUT_OF_MEMORY:
>                /* Do someting */
>                break;
>        case CELIX_RETURN_DEVIDE_BY_ZERO:
>                /* Do someting */
>                break;
>        default:
>                /* This is bad, return value not expected */
>                break;
> }
> Don't forget to keep Celix simple however ;).
> I agree with your idea to go for the easy solution. It will keep your
> code simple. As I showed, even without libex you can still make the code
> look very recognizable and if you really want to, with some defines you
> can make it look more TRY-CATCHY.

Good arguments, and I agree. I will start using the easy solution.

This raises an other question though, in the example you gave, there
is a dedicated CELIX_OUT_OF_MEM. Is it a good idea to redefine
existing errors from errno.h into "own" errors? Or should errors be
reused? Since I am looking at APR, I tried to see how they solved it,
an apparently they wrap existing number into their own:

>From https://svn.apache.org/repos/asf/apr/apr/trunk/include/apr_errno.h
#ifdef ENOMEM
#define APR_ENOMEM ENOMEM
#else
#define APR_ENOMEM         (APR_OS_START_CANONERR + 7)
#endif

I think it makes more sense to have dedicated CELIX_ errors. This
keeps the api clean in the way that the only reported errors are
CELIX_ errors. Basically what APR also does.

>
> I hope this information/thoughts helps,
> best regards,
> Bob Fels

This definitely helps! Looking forward to more remarks and your
insight in embedded code/platforms!


-- 
Kind regards,

Alexander Broekhuis

Re: Exception Handling in C

Posted by Marcel Offermans <ma...@luminis.nl>.
Hello Bob,

First of all, welcome to the list!

On Feb 13, 2011, at 19:01 , J.A. Fels wrote:

> This is my first commit on this mailing list, so Ill briefly introduce
> myself: I'm Bob Fels, software engineer in embedded real time systems.
> For that I mainly use C, but I am also experienced in C++, Java, Python,
> Perl, various assembly flavors etc.

That's definitely one of the areas we're targetting with Celix. Just out of interest, are you familiar with OSGi?

> I am every interested in using a service approach in embedded software,
> so Celix drew my interest.
> 
> * Using returns
> 
> For exception handling the most easy way is using states as return
> values of functions. This will keep your code really simple and you can
> still have predictable returns (and can still comply with Misra rule
> about one return per function).
> 
> The try-catch macros look nice indeed and looks like a good way to let
> it like like the Java manner of exception handling, but I think
> something like the following is very readable:
> 
> switch (my_function())
> {
> 	case CELIX_RETURN_OK:
> 		break;
> 	case CELIX_RETURN_OUT_OF_MEMORY:
> 		/* Do someting */
> 		break;
> 	case CELIX_RETURN_DEVIDE_BY_ZERO:
> 		/* Do someting */
> 		break;
> 	default:
> 		/* This is bad, return value not expected */
> 		break;
> }
> Don't forget to keep Celix simple however ;).

I agree that it's quite common in C to use return values to signal success or failure of a function. Maybe by adopting exceptions, we can keep some of the service API's a bit closer to their Java/OSGi equivalents, but the question is if that's worth the extra hassle of using those macros and adopting something that is less common to C programmers. I have a slight personal preference to sticking with using return values.

> * setjmp/longjmp
> 
> Using setjmp and longjmp is possible even for real time systems as
> exceptions should not be part of the normal flow of the application and
> thus in exceptional situations the main thing that matters is getting
> back to a stable state.
> 
> With setjmp and longjmp will make more return points in functions, so
> code flow will be harder to determine, as you can jump up multiple
> functions. Also you need to drag along that structure which has saved
> your stack, so it will be in every function call.
> 
> Its no problem at all for threads in principle as you just save the
> stack and instruction pointer. Don't use it between threads however, but
> that will not happen with try-catch either. The other danger is that
> because of the sudden "return" its very easy for example to forget to
> release locks.
> 
> Advantage is that it indeed does exactly the same as a throw in Java.

I have little experience with setjmp/longjmp (it's been a while since I've used C).

> * Conclusion
> 
> I agree with your idea to go for the easy solution. It will keep your
> code simple. As I showed, even without libex you can still make the code
> look very recognizable and if you really want to, with some defines you
> can make it look more TRY-CATCHY.

+1 :)

> 
> I hope this information/thoughts helps,
> best regards,
> Bob Fels
> 
> 
> On Sun, 2011-02-13 at 13:36 +0100, Alexander Broekhuis wrote:
>> Hello everyone,
>> 
>> Now that everything is in SVN, I would like to start working on the code again.
>> 
>> There is one important aspect which still needs a solution: Exception handling
>> Celix follows the OSGi spec (Java), but since C doesn't have
>> exceptions like Java, a solution is needed to be able to report
>> errors/exceptions.
>> 
>> I've been looking on the web, and found 2 possible solutions.
>> 
>> 1) Using a library that uses setjmp/longjmp:
>> Examples are:
>> - http://libexcept.sourceforge.net/
>> - http://www.nicemice.net/cexcept/
>> - http://code.google.com/p/exceptions4c/
>> 
>> 2) Use the return value of functions:
>> - For example by simply returning a int value indicating the error
>> - Use a library which supplies try/catch macros: http://code.google.com/p/libex/
>> 
>> The first solution makes it possible to have an API very similar to
>> the OSGi spec, but I am not sure how setjmp and longjmp interact with
>> threads and real time behavior.
>> The second solution is the most simple, and with the help of a library
>> it is still possible to have clear code with try/catch constructs.
>> 
>> Does anyone have any experience with these kind of libraries?
>> 
>> For now I tend to lean towards using a simple solution, either simply
>> returning the error code, or using something like libex (which is
>> lgpl, which might be a problem..).
>> 
> 
> 


Re: Exception Handling in C

Posted by "J.A. Fels" <tr...@gmail.com>.
Hello everyone,

This is my first commit on this mailing list, so Ill briefly introduce
myself: I'm Bob Fels, software engineer in embedded real time systems.
For that I mainly use C, but I am also experienced in C++, Java, Python,
Perl, various assembly flavors etc.

I am every interested in using a service approach in embedded software,
so Celix drew my interest.

* Using returns

For exception handling the most easy way is using states as return
values of functions. This will keep your code really simple and you can
still have predictable returns (and can still comply with Misra rule
about one return per function).

The try-catch macros look nice indeed and looks like a good way to let
it like like the Java manner of exception handling, but I think
something like the following is very readable:

switch (my_function())
{
	case CELIX_RETURN_OK:
		break;
	case CELIX_RETURN_OUT_OF_MEMORY:
		/* Do someting */
		break;
	case CELIX_RETURN_DEVIDE_BY_ZERO:
		/* Do someting */
		break;
	default:
		/* This is bad, return value not expected */
		break;
}
Don't forget to keep Celix simple however ;).

* setjmp/longjmp

Using setjmp and longjmp is possible even for real time systems as
exceptions should not be part of the normal flow of the application and
thus in exceptional situations the main thing that matters is getting
back to a stable state.

With setjmp and longjmp will make more return points in functions, so
code flow will be harder to determine, as you can jump up multiple
functions. Also you need to drag along that structure which has saved
your stack, so it will be in every function call.

Its no problem at all for threads in principle as you just save the
stack and instruction pointer. Don't use it between threads however, but
that will not happen with try-catch either. The other danger is that
because of the sudden "return" its very easy for example to forget to
release locks.

Advantage is that it indeed does exactly the same as a throw in Java.

* Conclusion

I agree with your idea to go for the easy solution. It will keep your
code simple. As I showed, even without libex you can still make the code
look very recognizable and if you really want to, with some defines you
can make it look more TRY-CATCHY.

I hope this information/thoughts helps,
best regards,
Bob Fels


On Sun, 2011-02-13 at 13:36 +0100, Alexander Broekhuis wrote:
> Hello everyone,
> 
> Now that everything is in SVN, I would like to start working on the code again.
> 
> There is one important aspect which still needs a solution: Exception handling
> Celix follows the OSGi spec (Java), but since C doesn't have
> exceptions like Java, a solution is needed to be able to report
> errors/exceptions.
> 
> I've been looking on the web, and found 2 possible solutions.
> 
> 1) Using a library that uses setjmp/longjmp:
> Examples are:
> - http://libexcept.sourceforge.net/
> - http://www.nicemice.net/cexcept/
> - http://code.google.com/p/exceptions4c/
> 
> 2) Use the return value of functions:
> - For example by simply returning a int value indicating the error
> - Use a library which supplies try/catch macros: http://code.google.com/p/libex/
> 
> The first solution makes it possible to have an API very similar to
> the OSGi spec, but I am not sure how setjmp and longjmp interact with
> threads and real time behavior.
> The second solution is the most simple, and with the help of a library
> it is still possible to have clear code with try/catch constructs.
> 
> Does anyone have any experience with these kind of libraries?
> 
> For now I tend to lean towards using a simple solution, either simply
> returning the error code, or using something like libex (which is
> lgpl, which might be a problem..).
>