473,378 Members | 1,346 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Is setjmp/longjmp ok?

Should setjmp/longjmp really be used in a fast mundane ANSI C piece of
code? Or is it frowned apon like goto? I have a need but I don't want to
use something that is costly, isn't supported consistenly, or something
that might pull in exotic text segments, etc.

Specifically I have a hairly algorithm loop that uses what is currently
a macro V. Here's a snipplet:

for (k = d; k >= -d; k -= 2) {
if (k == -d || (k != d && V(fwd, m, k - 1) < V(fwd, m, k + 1))) {
x = V(fwd, m, k + 1);
} else {
x = V(fwd, m, k - 1) + 1;
}
y = x - k;

But now I must replace the V macro with a function (say vfn) that will
need to indicate an error has occured. The question is do I;

A) replace each macro V with a function that returns -1 to indicate an
error has occured and check it with each call like:

for (k = d; k >= -d; k -= 2) {
int v1 = vfn(fwd, m, k - 1);
int v2 = vfn(fwd, m, k + 1);
if (v1 == -1 || v2 == -1) {
return -1;
}
if (k == -d || (k != d && v1 < v2)) {
if ((x = vfn(fwd, m, k + 1)) == -1) {
return -1;
}
... yuk - and vfn is called regardless of
whether or not k == -d or k == d

or

B) use longjmp when the error occurs to cleanly return regardless of
the state of the hairy loop like:

if (setjmp(env) == 1) {
return -1;
}
for (k = d; k >= -d; k -= 2) {
if (k == -d || (k != d && vfn(fwd, m, k - 1, &env) < vfn(fwd, m, k + 1, &env))) {
x = vfn(fwd, m, k + 1, &env);
} else {
...

where vfn calls longjmp when the error occurs like:

longjmp(*env, 1);

Thanks,
Mike
Nov 14 '05 #1
12 3278
Michael B Allen wrote:
Should setjmp/longjmp really be used in a fast mundane ANSI C piece of
code? Or is it frowned apon like goto? I have a need but I don't want to
use something that is costly, isn't supported consistenly, or something
that might pull in exotic text segments, etc.


setjmp/longjmp tends to be supported across a lot of platforms, so I
wouldn't worry about its unavailability.

The most frequent usage is in signal handlers, e.g., signal(SIGINT,
your_function_here), to return back to main() or an event loop.

While your usage isn't particularly evil, why would you want to complicate
your code with non-local gotos if you can unwind the stack cleanly? longjmp
may return you back a little faster, but YMMV.
Nov 14 '05 #2
Michael B Allen wrote:
Should setjmp/longjmp really be used in a fast mundane ANSI C piece of
code? Or is it frowned apon like goto? I have a need but I don't want to
use something that is costly, isn't supported consistenly, or something
that might pull in exotic text segments, etc.


setjmp/longjmp tends to be supported across a lot of platforms, so I
wouldn't worry about its unavailability.

The most frequent usage is in signal handlers, e.g., signal(SIGINT,
your_function_here), to return back to main() or an event loop.

While your usage isn't particularly evil, why would you want to complicate
your code with non-local gotos if you can unwind the stack cleanly? longjmp
may return you back a little faster, but YMMV.
Nov 14 '05 #3
On Fri, 30 Apr 2004 20:51:10 -0700, -wombat- <sc****@cs.ucla.edu>
wrote in comp.lang.c:
Michael B Allen wrote:
Should setjmp/longjmp really be used in a fast mundane ANSI C piece of
code? Or is it frowned apon like goto? I have a need but I don't want to
use something that is costly, isn't supported consistenly, or something
that might pull in exotic text segments, etc.
setjmp/longjmp tends to be supported across a lot of platforms, so I
wouldn't worry about its unavailability.


All implementations of C for hosted environments support setjmp and
longjmp. Anything that does not, in a hosted environment, is not a C
implementation regardless of claims to the contrary.
The most frequent usage is in signal handlers, e.g., signal(SIGINT,
your_function_here), to return back to main() or an event loop.
Calling longjmp in a signal handler that was invoked asynchronously,
that is other than by a call to raise() or abort(), produces undefined
behavior.
While your usage isn't particularly evil, why would you want to complicate
your code with non-local gotos if you can unwind the stack cleanly? longjmp
may return you back a little faster, but YMMV.


Generally speaking, the need to use longjmp in an ordinary program for
ordinary error handling indicates a need for a better design. They
are exceptions, of course, but they are very, very few.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #4
Jack Klein wrote:
On Fri, 30 Apr 2004 20:51:10 -0700, -wombat- <sc****@cs.ucla.edu>
wrote in comp.lang.c:
The most frequent usage is in signal handlers, e.g., signal(SIGINT,
your_function_here), to return back to main() or an event loop.


Calling longjmp in a signal handler that was invoked asynchronously,
that is other than by a call to raise() or abort(), produces undefined
behavior.


Many years ago, when only the K&R manual existed as a mere hint of a spec
and AT&T 3b2s were current hardware, that's what I was using setjmp and
longjmp for -- mostly in daemon processes when something got into trouble
and we wanted to hit the daemon with a signal to get it to jump back to its
read() loop. So we used longjmp to return more than one level in the stack
back.

"undefined behavior" is a little strong (it's spec-speak for "Programmer!
CYA!") "unpredictable" is more apropos because the programmer now has to be
careful that whatever the longjmp returns to has some kind of sane state or
at least some state that can be salvaged. The onus is on the coder to DTRT.
Besides, the signal handler's stack frame should be deeper than the
original setjmp's caller's (hopefully), so there's really no major problem
even if the handler is called async. Of course, there are a lot of ways to
get this wrong.

Other creative uses I've seen of setjmp/longjmp is in Scheme-to-C call/cc
support as well as primitive, non-preemptive user-level thread packages
(yield() is just a call to setjmp to save current thread state and longjmp
back to the thread scheduler.) In the latter case, most OSs have some kind
of thread support so there's no longer a real need for that hack.

Nov 14 '05 #5
On Sat, 01 May 2004 16:34:47 -0400, Jack Klein wrote:
While your usage isn't particularly evil, why would you want to
complicate your code with non-local gotos if you can unwind the stack
cleanly? longjmp may return you back a little faster, but YMMV.


Generally speaking, the need to use longjmp in an ordinary program for
ordinary error handling indicates a need for a better design. They are
exceptions, of course, but they are very, very few.


You said "exceptions" and that is precisely what the example given needs
-- an exception handler. The purpose of an exception handler is to provide
error handling without disrupting the normal flow of the primary code
path. Considering C does not have exceptions setjmp/longjmp is the next
closest thing.

But then I suppose my question has been answered -- using setjmp/longjmp
in this context is perceived as complicated or poor design.

Mike
Nov 14 '05 #6
-wombat- <sc****@cs.ucla.edu> wrote:
Jack Klein wrote:
On Fri, 30 Apr 2004 20:51:10 -0700, -wombat- <sc****@cs.ucla.edu>
wrote in comp.lang.c:
The most frequent usage is in signal handlers, e.g., signal(SIGINT,
your_function_here), to return back to main() or an event loop.
Calling longjmp in a signal handler that was invoked asynchronously,
that is other than by a call to raise() or abort(), produces undefined
behavior.


Many years ago, when only the K&R manual existed as a mere hint of a spec
and AT&T 3b2s were current hardware, that's what I was using setjmp and
longjmp for


And in those years, such functions behaved differently - often not at
all, or very system-dependently. Today, we have harnessed the power of
fire, and we have the Standard.
"undefined behavior" is a little strong (it's spec-speak for "Programmer!
CYA!")
Undefined behaviour is _exactly_ right:

# [#5] If the signal occurs other than as the result of
# calling the abort or raise function, the behavior is
# undefined if ...
# ... or the signal
# handler calls any function in the standard library other
# than the abort function or the signal function with the
# first argument equal to the signal number corresponding to
# the signal that caused the invocation of the handler.

That's from n869, btw. I believe the actual Standard says the same.
"unpredictable" is more apropos because the programmer now has to be
careful that whatever the longjmp returns to


Once you call longjmp() from a signal handler, it is not even guaranteed
_that_ you return anywhere, let alone that it is stable.

Richard
Nov 14 '05 #7

In article <pa**********************************@ioplex.com >, Michael B Allen <mb*****@ioplex.com> writes:

But then I suppose my question has been answered -- using setjmp/longjmp
in this context is perceived as complicated or poor design.


Certainly it is by some, but the same can be said of essentially any
C construct. You can get good style advice from comp.lang.c, but
when you're considering alternatives that are equally valid per the
standard, remember that style recommendations are subjective. There
may be good arguments to be made in their favor, but not on the same
order as "this produces undefined behavior" or the like.

In this particular case, for example, setjmp / longjmp wouldn't
bother me, if I saw them in code I was maintaining. Their use would
be confined to a small segment of code and the application is clear.
I would prefer to see the jmp_buf passed as a parameter to the
function calling longjmp, though.

--
Michael Wojcik mi************@microfocus.com

Although he was an outsider, and excluded from their rites, they were
always particularly charming to him at this time; he and his household
received small courtesies and presents, just because he was outside.
-- E M Forster
Nov 14 '05 #8
Richard Bos wrote:
"undefined behavior" is a little strong (it's spec-speak for "Programmer!
CYA!")


Undefined behaviour is _exactly_ right:

# [#5] If the signal occurs other than as the result of
# calling the abort or raise function, the behavior is
# undefined if ...
# ... or the signal
# handler calls any function in the standard library other
# than the abort function or the signal function with the
# first argument equal to the signal number corresponding to
# the signal that caused the invocation of the handler.

That's from n869, btw. I believe the actual Standard says the same.


It's saying that the standard library makes no gaurantees if anything other
than raise() or abort() are called. That's not to say that things don't
work -- plenty of software out there actually does call standard library
functions from inside signal handlers, SIGINT being the prime example.
"unpredictable" is more apropos because the programmer now has to be
careful that whatever the longjmp returns to


Once you call longjmp() from a signal handler, it is not even guaranteed
_that_ you return anywhere, let alone that it is stable.


Your scenario only makes sense if the signal handler is called with a
separate stack, but even then that tends to fly in the face of reality.
jmp_buf saves a lot of machine state, including the stack pointer. Since
setjmp is generally called in an upper stack frame vs. longjmp being called
in a lower stack frame, it's not completely unstable and the return point
isn't totally undefined. The only place/time that can happen is if the
programmer violates the up/down ordering of stack frames, which would
indicate that the programmer doesn't understand how to use setjmp or
longjmp properly.

Besides, if what you said is true, a lot of software would cease to work.
Can the programmer do some bad things to the software by using
setjmp/longjmp? Yes. Does it take a lot of extra thinking to work with
setjmp/longjmp? Yes.
Nov 14 '05 #9
On Sun, 02 May 2004 00:00:04 -0400, Michael B Allen
<mb*****@ioplex.com> wrote:
On Sat, 01 May 2004 16:34:47 -0400, Jack Klein wrote:
While your usage isn't particularly evil, why would you want to
complicate your code with non-local gotos if you can unwind the stack
cleanly? longjmp may return you back a little faster, but YMMV.


Generally speaking, the need to use longjmp in an ordinary program for
ordinary error handling indicates a need for a better design. They are
exceptions, of course, but they are very, very few.


You said "exceptions" and that is precisely what the example given needs
-- an exception handler. The purpose of an exception handler is to provide
error handling without disrupting the normal flow of the primary code
path. Considering C does not have exceptions setjmp/longjmp is the next
closest thing.

But then I suppose my question has been answered -- using setjmp/longjmp
in this context is perceived as complicated or poor design.

Not always. It's like goto, it may be a sign of poor design, but there
are places where it's appropriate.

Having said that, I must admit that I've almost never had a situation
where it was appropriate, and when I've seen setjmp/longjmp while
maintaining old code, there has almost always been a better way.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #10
Alan Balmer wrote:
Michael B Allen <mb*****@ioplex.com> wrote:

.... snip ...

But then I suppose my question has been answered -- using
setjmp/longjmp in this context is perceived as complicated or
poor design.


Not always. It's like goto, it may be a sign of poor design, but
there are places where it's appropriate.

Having said that, I must admit that I've almost never had a
situation where it was appropriate, and when I've seen
setjmp/longjmp while maintaining old code, there has almost
always been a better way.


To all practical purposes the presence of exit() and atexit()
obviate most needs for setjmp/longjmp. The glaring exception
would be when you don't want to let the user access the underlying
machine in any circumstances, and even then you probably want
passworded code to exit the process for maintenance purposes.

--
"I'm a war president. I make decisions here in the Oval Office
in foreign policy matters with war on my mind." - Bush.
"Churchill and Bush can both be considered wartime leaders, just
as Secretariat and Mr Ed were both horses." - James Rhodes.
Nov 14 '05 #11
-wombat- <sc****@cs.ucla.edu> wrote:
Richard Bos wrote:
"undefined behavior" is a little strong (it's spec-speak for "Programmer!
CYA!")
Undefined behaviour is _exactly_ right:

# [#5] If the signal occurs other than as the result of
# calling the abort or raise function, the behavior is
# undefined if ...
# ... or the signal
# handler calls any function in the standard library other
# than the abort function or the signal function with the
# first argument equal to the signal number corresponding to
# the signal that caused the invocation of the handler.

That's from n869, btw. I believe the actual Standard says the same.


It's saying that the standard library makes no gaurantees if anything other
than raise() or abort() are called.


Exactly. And this is called undefined behaviour in the Standard.
That's not to say that things don't
work -- plenty of software out there actually does call standard library
functions from inside signal handlers, SIGINT being the prime example.
Sure, but those programs assume C _and_ something else, often POSIX.
What POSIX defines in addition, or possibly even contradiction, to the
ISO C Standard is off-topic here, since this is a newsgroup about C, not
about C-for-some-popular-OSes-only.
"unpredictable" is more apropos because the programmer now has to be
careful that whatever the longjmp returns to


Once you call longjmp() from a signal handler, it is not even guaranteed
_that_ you return anywhere, let alone that it is stable.


Your scenario only makes sense if the signal handler is called with a
separate stack,


No - my scenario is explicitly allowed by the Standard. Who knows - it
might be a safety feature of the OS. My point is that _unless_ you
assume additional, off-topic, standards you cannot assume that calling
longjmp() from a signal handler does anything at all.
Besides, if what you said is true, a lot of software would cease to work.


Nonsense. What I say is true, and a lot of software is not written
entirely in ISO C.

Richard
Nov 14 '05 #12
Richard Bos wrote:
>> "unpredictable" is more apropos because the programmer now has to be
>> careful that whatever the longjmp returns to
>
> Once you call longjmp() from a signal handler, it is not even
> guaranteed _that_ you return anywhere, let alone that it is stable.


Your scenario only makes sense if the signal handler is called with a
separate stack,


No - my scenario is explicitly allowed by the Standard. Who knows - it
might be a safety feature of the OS. My point is that _unless_ you
assume additional, off-topic, standards you cannot assume that calling
longjmp() from a signal handler does anything at all.
Besides, if what you said is true, a lot of software would cease to work.


Nonsense. What I say is true, and a lot of software is not written
entirely in ISO C.


The language has to assume a machine model, without which the language is
utterly useless. The language maps to that hypothetical, perfect virtual
machine. setjmp/longjmp make certain assumptions based on the VM's
structure such that it has validity and will work. One of those VM features
is a stack-based architecture, without which, a lot of C features would be
hard to implement (not impossible, but much harder.)

What you've incorrectly asserted is that "What the standard says must
arbitrarily be true." The standard gives the RTL implementor leeway in the
RTL's implementation such that no gauruntees have to be made in special
situations. No more and no less. Thus, if something doesn't work, the RTL
implementor can point to the standard and assert that they implemented the
standard correctly.

Nothing I said had to do with special OS support structures. I merely
pointed out some of the more common uses of setjmp/longjmp. Moreover, I
pointed how reality (and the VM that maps to the C language) tends to fly
in the face of what the ISO standard would call "undefined" behavior.

But, hey, must be nice to live inside the ISO standard cocoon. Meanwhile,
there's reality for the rest of us.
Nov 14 '05 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: alexey_m | last post by:
Hi! I try to use setjmp/longjmp instructions, but application fails with KERN-EXEC 3. Code is very simple: int Main() { jmp_buf jump_buffer; if ( setjmp( jump_buffer ) == 0 ) { longjmp(...
2
by: Mantorok Redgormor | last post by:
is there a portable way of implementing exception handling with setjmp, longjmp? restoring the state of a program and such really seems like I am asking for undefined behavior. -- nethlek
6
by: someone | last post by:
I have *thought* that setjmp/longjmp() should take a pointer to jmp_buf. And the calling function should hold the actual struct data. But ... I trid on both Win32 and Linux, it seems that...
0
by: Michael B Allen | last post by:
Should setjmp/longjmp really be used in a fast mundane ANSI C piece of code? Or is it frowned apon like goto? I have a need but I don't want to use something that is costly, isn't supported...
2
by: Ravi Uday | last post by:
Hi, Can anyone explain me why do we use setjmp and longjump functions. I read through the manual pages/doc but wasnt able to get a clear picture of the same. Any small example illustrating...
4
by: Jrferguson | last post by:
I have a C program that I am trying to port to a Motorola 68k based system. It makes use of setjmp and longjmp which are not supported by my C compiler. I understand the general principle behind...
8
by: Zheng Da | last post by:
I wrote a simple one as follow: typedef struct __myjmp_buf { int efp; int epc; }myjmp_buf; int mysetjmp(myjmp_buf env) {
3
by: no_click_there | last post by:
Hi, I'm learning to use the setjmp/longjmp functions and still can't really grasp what's going on here. I'd basically like to be able to jump back and forth from (or to) two given functions. ...
0
by: sh.vipin | last post by:
Based on some study about setjmp / longjmp I have developed following notions about setjmp / longjmp . Would like to get feedback on them ?? Q1. Is there any point in keeping jmp_buf variable...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.