tags:

views:

582

answers:

7

So, I have a big piece of legacy software, coded in C. It's for an embedded system, so if something goes wrong, like divide by zero, null pointer dereference, etc, there's not much to do except reboot.

I was wondering if I could implement just main() as c++ and wrap it's contents in try/catch. That way, depending on the type of exception thrown, I could log some debug info just before reboot.

Hmm, since there are multiple processes I might have to wrap each one, not just main(), but I hope that you see what I mean...

Is it worthwhile to leave the existing C code (several 100 Klocs) untouched, except for wrapping it with try/catch?

+4  A: 

Since it's an embedded application it probably runs only on one platform.

If so its probably much simpler and less intrusive to install a proper interrupt handler / kernel trap handler for the division by zero and other hard exceptions.

In most cases this can be done with just a few lines of code. Check if the OS supports such installable exception handlers. If you're working on an OS-less system you can directly hook the CPU interrupts that are called during exceptions.

Nils Pipenbrinck
"Since it's an embedded application it probably runs only on one platform."What an odd statement!
Vicky
Odd? From experience it sounds very believable. I've worked for a large telecom manufacturer which ran their 68030 CPUs with cache disabled, as it made them "more compatible" with the original 68000s they used before. The notion of "application failure = device reboot" also strongly hints at a device built for a single application. Why choose two different platforms for that single application? (Two vendors, OK, but you'd still select two ARM vendors or 2 MIPS vendors)
MSalters
Running embedded software on one single platform is very common. Usually you have a design with custom peripherals that you don't find elsewhere and it's cost optimized (e.g peripherials hard-wired to GPIO-pins ect.) Changing such from one platform to another often requires a complete rewrite of at least the IO-layer.
Nils Pipenbrinck
I agree that there are embedded systems that are only designed / implemented to run on one platform. However, I don't believe that "Since it is an embedded application it probably only runs on one platform" is valid.
Vicky
OP: I really gave bad examples with division by zero, null pointer deref, sorry.let's agree that these need to be handled by signals/interrupts/whatever. And let's agree to think in the general case (multiple platforms) whether needed or not.If I compile my C code as C++ then the compiler will generate throws as needed and I can add an outer wrapper of try/catch. Does that seem like it might be useful?
mawg
+11  A: 

Division by zero or null pointer dereferencing don't produce exceptions (using the C++ terminology). C doesn't even have a concept of exceptions. If you are on an UNIX-like system, you might want to install signal handlers (SIGFPE, SIGSEGV, etc.).

Lukáš Lalinský
mawg
No, C code will never throw any C++ exception.
Lukáš Lalinský
yes, I know that C will never throw a C++ exception. But if I compile C code as if it were C++ (since C is a valid subset of C++ (and a lot of programmers when told to code in C++ just switch compilers and continue to code in C :-)), then treating the C as if it were C++ (might have to rename all files to change C *.c to *.cpp; might just need to use a different compiler), *then* the generated code will be ready to throw execptions, even though I don't change the code.That is what I am trying to achieve - but I am afraid that I am not explaining it very well ... sorry
mawg
Yes, it will be ready to throw exceptions, but it will not throw exceptions on it's own. You would have to either use a library that throws exceptions or throw exceptions manually. But if you are doing this only for rebooting the device, I don't see the benefit. Instead of `throw Something();` you could call `ERROR();`.
Lukáš Lalinský
+4  A: 

I don't think machine code compiled from C does the same thing with regard to exceptions, as machine code compiled for C++ which "knows" about exceptions. That is, I don't think it's correct to expect to be able to catch "exceptions" from C code using C++ constructs. C doesn't throw exceptions, and there's nothing that guarantees that errors that happen when C code does something bad are caught by C++'s exception mechanism.

unwind
Agreed, C doesn't have exceptions. What I poorly explained was that I want to wrap my C code in C++, thus making into C++ code - which only uses a small subset of the language, but which then have exception handling added by teh compiler.
mawg
+4  A: 

First of all, divide by zero or null pointer dereference won't throw exceptions. Fpe exceptions are implemented in the GNU C library with signals (SIGFPE). And are part of the C99 standard, not the C++ standard.

A few hints based in my experience in embedded C and C++ development. Depending on your embedded OS:

  • Unless you are absolutely sure of what you are doing, don't try/catch between threads . Only inside the same thread. Each thread usually has its own stack.
  • Throwing in the middle of legacy C code and catching, is going to lead to problems, since for example when you have jumped to the catch block out of the normal program flow, allocated memory may not be reclaimed, thus you have leaks which is far more problematic than divide by zero or null pointer dereference in an embedded system.
  • If you are going to use exceptions, throw them inside your C++ code with allocation of other "C" resources in constructors and deallocation in destructors.
  • Catch them just above the C++ layer.
piotr
A: 

I think I remember researching on how to handle SIGSEGV ( usually generated when derefing invalid pointer, or dividing by 0 ) and the general advise I found on the net was: do nothing, let the program die. The explanation, I think a correct one, is that by the time you get to a SIGSEGV trap, the stack of the offending thread is trashed beyond repair.

Can someone comment if this is true?

Alexander Pogrebnyak
He wanted to reboot the device after receiving `SIGSEGV`, not try to repair it.
Lukáš Lalinský
I agree - except for letting it die. On embedded systems you generally want to reboot. I was just hoping to catch as much debug info as possible before dieing/rebooting.
mawg
+1  A: 

Divide by zero, null pointer dereference are not C or C++ exceptions they are hardware exceptions.

On Windows you can get hardware exceptions like these wrapped in a normal C++ exception if _set_se_translator() is used.

__try/__catch may also help. Look up __try/__catch, GetExceptionCode(), _set_se_translator() on MSDN, you may find what you need.

Stuart
A: 

Only work on msvc

      
__try
{

int p = 0;
p=p / 0;
}
__except (1)
{
printf("Division by 0 \n");
}
Arabcoder