views:

1206

answers:

3

Hi,

Is it safe to use longjmp and setjmp in C++ on linux/gcc with regards to the following?

  1. Exception handling (I'm not implementing exception handling using longjmp/setjmp. I want to know what side effects longjmp/setjmp will have on standard exception handling)
  2. *this pointer
  3. Signals
  4. Smart pointers (boost's shared and intrusive pointers)
  5. Anything else you can think of.

Thanks, James

+22  A: 

setjmp()/longjmp() completely subvert stack unwinding and therefore exception handling as well as RAII (destructors in general).

From 18.7/4 "Other runtime support" in the standard:

If any automatic objects would be destroyed by a thrown exception transferring control to another (destination) point in the program, then a call to longjmp(jbuf, val) at the throw point that transfers control to the same (destination) point has undefined behavior.

So the bottom line is that setjmp()/longjmp() do not play well in C++.

Michael Burr
Can you explain how longjmp messes with explicit memory deletion and destructors?
jameszhao00
Generally, whenever there's some way to exit a scope in C++ (return, throw, or whatever), the compiler will place instructions to call the dtors for any automatic variables that need to be destroyed as a result of leaving that block. `longjmp()` just jumps to a new location in the code, so it will not provide any chance for the dtors to be called. The standard is actually less specific than that - the standard doesn't say that dtors won't be called - it says that all bets are off. You can't depend on any particular behavior in this case.
Michael Burr
I'm not too familiar with smart pointers. If I have a smart pointer on the stack, when I do a longjmp does that mean the smart pointer won't remove a refcount? Also, am I safe if I disable exceptions and write code that doesn't go crazy with longjmp?
jameszhao00
Since smart pointers depend on being destroyed, you will get undefined behavior. It's likely that that undefined behavior would include a refcount not getting decremented. You're 'safe' using `longjmp()` as long as you don't longjmp out of code that should cause dtors to be invoked. However, as David Thornley noted in a comment, setjmp()/longjmp() can be tricky to use right even in straight C - in C++ they're downright dangerous. Avoid them if at all possible.
Michael Burr
@jameszhao00: If you don't know smart pointers well enough, (get familiar with them ASAP an for now) think other things: `std::vector` and `std::string` not freeing its memory, `std::fstream` not closing its file and things like this.
sbi
Can you take a quick look at http://stackoverflow.com/questions/1381937/setjmp-longjmp-why-is-this-throwing-a-segfault ?
jameszhao00
A: 

I have only learned about those commands, and never seen them in action in real applications.

IMHO, it's safe to say that it's not safe to use them: developers will not understand what those "unpopular" APIs do.

elcuco
This is for a coroutines implementation (which require randomly jumping around)
jameszhao00
Experienced developers will absolutely know what these "unpopular" APIs do. They have been a part of the standard C library for decades.
Novelocrat
Experienced developers will absolutely know what these functions do. They will also know that they are tricky things to use right in C (although sometimes necessary), and extremely dangerous in C++.
David Thornley
A: 

It's not specific to Linux or gcc; setjmp / longjmp and C++ don't work too well together if you're using longjmp to leave a context where there are automatic variables with destructors.

The destructors won't run which may result in a memory leak or other bad behaviour.

MarkR