How to (computed) goto and longjmp in C++?
Asked Answered
S

7

12

I don't usually code C++, but a strange comp sci friend of mine got sick of looking at my wonderful FORTRAN programs and challenged me to rewrite one of them in C++, since he likes my C++ codes better. (We're betting money here.) Exact terms being that it needs to be compilable in a modern C++ compiler. Maybe he hates a good conio.h - I don't know.

Now I realize there are perfectly good ways of writing in C++, but I'm going for a personal win here by trying to make my C++ version as FORTRAN-esque as possible. For bonus points, this might save me some time and effort when I'm converting code.

SO! This brings me to the following related queries:

On gotos:

  1. How do you work a goto?
  2. What are the constraints on gotos in C++?
  3. Any concerns about scope? (I'm going to try to globally scope as much as possible, but you never know.)
  4. If I use the GCC extension to goto to a void pointer array, are there any new concerns about undefined behavior, etc?


On longjmp:

  1. How would you safely use a longjmp?
  2. What are the constraints on longjmps in C++?
  3. What does it do to scope?
  4. Are there any specific moments when it looks like a longjmp should be safe but in fact it isn't that I should watch out for?
  5. How would I simulate a computed goto with longjmp?
  6. Is there any tangible benefit to using longjmp over goto if I only have one function in my program?

Right now my main concern is making a computed goto work for this. It looks like I'll probably use the longjmp to make this work because a void pointer array isn't a part of the C++ standard but a GCC specific extension.

Stereoisomerism answered 28/9, 2011 at 18:53 Comment(20)
Cue deluge of non-answers condemning gotos in 3... 2... 1...Antonetteantoni
Thank you for attempting to proving that, literally, "real programmers can write FORTRAN in any language" :)Befall
If you're writing "FORTRAN-esque" C++ then you're not writing C++. If I were in the bet then you'd have hard times convincing me you did your part.Unruh
Can we at least make fun of FORTRAN?Electrokinetic
I think I used to work with this guy at my old job!Greenhead
You can make fun of whatever you want, but if you post an answer I expect it to be a proper answer. Also, wilhelmtell, there were exact terms to our bet.Stereoisomerism
+1 for original question, although personally i think you are doing a creative attempt of getting answers for your homework. :)Tartarus
Anders K, I'm pretty sure these days there aren't really C++ teachers who make you use gotos and longjmps. Usually they promise zeroes if you use them. And you haven't seen creative yet. I'm considering abusing the holy hell out of defines and overloading so that I won't even have to rewrite my FORTRAN.Stereoisomerism
that remembers me the day i implemented an Ada oriented exception handling mechanism in C, using gotos, longjmp and #defines... i had great fun writing and testing this, but was never able to use it in the real-world, fearing the wrath of my workmates.Elmaelmajian
This is a real question. Just because you don't like goto is not a reason to close this post!Baugh
It's not difficult to tell what is being asked here. This question is not ambiguous, vague, incomplete, overly broad, or rhetorical and can be reasonably answered in its current form. When voting to close please don't pick a reason at random.Henequen
@John Dibling: I voted to close as Not Constructive because writing intentionally complex FORTRAN in C++ and soliciting swarms of "goto is bad" comments and debate is not helpful to anyone.Tesstessa
Related: https://mcmap.net/q/24147/-can-goto-jump-across-functions-without-destructors-being-called/46642, https://mcmap.net/q/21800/-c-safe-to-use-longjmp-and-setjmp/46642 and many others.Haimes
@AJG85, my intention can be nonconstructive, sure but my question is still perfectly constructive, and someone else looking at this question might have a more constructive purpose (like debugging someone else's code or whatever).Stereoisomerism
Here's what you should have tried before asking this: stackoverflow.com/questions/tagged/c%2b%2b%20longjmp and stackoverflow.com/questions/tagged/c%2b%2b%20gotoHaimes
@R. Martinho Fernandes: Useful? Yes. Answering all parts of my question? No.Stereoisomerism
@CodeMaker: Why is this a question about C++? You are not using a single feature of C++ that isn't readily available in C. You aren't using objects, since everything is global. You're not using templates. You're not using reasonable structures of any kind. So what about this question makes it about C++? Indeed, being C++ means that you have the possibility to screw all kinds of things up that C cannot.Cuttle
@NicolBolas, I suppose because my good friend requested that I be coding it in C++, because the goto and longjmp still constitute a part of C++, and because I should have concerns about the behavior and requirements on gotos and longjmps in a C++ context where there might be subtle but crucial differences from how they would behave in C, which I am not doing.Stereoisomerism
"If I use the GCC extension to goto to a void pointer array, are there any new concerns about undefined behavior" <-- this is the point where my head asploded :^)Benevolent
@NicolBolas: C++ has better type safety than C.Kletter
I
7

I'll bite and take the downvote.

I seriously doubt that your friend will find Fortran written in C++ any easier (which is effectively what you'll get if you use goto and longjmp significantly) to read and he might even find it harder to follow. The C++ language is rather different from Fortran and I really don't think you should attempt a straight conversion from Fortran to C++. It will just make the C++ harder to maintain and you might as well stay with your existing codebase.

goto: You set up a label (my_label:) and then use the goto command goto my_label; which will cause your program flow to execute at the statement following the goto. You can't jump past the initialization of a variable or between functions. You can't create an array of goto targets but you can create an array of object or function pointers to jump to.

longjmp: There is no reason to prefer longjmp over goto if you have only one function. But if you have only one function, again, you really aren't writing C++ and you'll be better off in the long run just maintaining your Fortran.

Inflate answered 28/9, 2011 at 19:5 Comment(10)
Then your goal needs revision.Tesstessa
I don't see why my goal is your affair. The question is still legitimate.Stereoisomerism
@Code Maker: I just think this is more appropriate topic for the bar over some beers than a Q&A forum online. No one else will benefit from the answer, writing intentionally complex and convoluted code serves no real purpose, and frankly you're more likely to generate a goto witch hunt than get any real answers anyway.Tesstessa
@AJG85, "no one else will benefit from the answer" my foot. I am asking general questions about goto and longjmps. Anyone who needs to brush up on these things and is concerned about any specifics of their use would benefit from this question.Stereoisomerism
@CodeMaker You're asking general questions about gotp and longjmps that can easily be answered by reading documentation. If the "General Reference" close reason had been implemented already, I'd vote to close as that. The ideal answer to your question would basically be a rehash of that documentation.Haimes
Well it's not implemented atm, and "general reference" can be a fuzzy ground when there are compiler specific considerations, etc. at work. Like I just found out that GCC allows you to use void pointers for goto labels. That changes things.Stereoisomerism
@CodeMaker: A "general question about goto and longjmps" in C++ is answered very simple. "Use goto when not using goto would make your code more obfuscated than the goto does." And "longjmp annihilates automatic variables, so you should never use it in C++". How goto works is something any C++ book teaches. GCC extensions are expressly not C++ and therefore are not a part of how goto works. So yes, everything you have asked for is general reference material, or has been asked and answered before.Cuttle
@NicolBolas: I am asking about performing computed goto type behavior and how to use longjmp in C++. And since you have so kindly stressed that longjmp does problematic things to C++ and therefore it's avoided, that makes it all the more important to know about the uses and risks of longjmp in C++, which do not appear to be well-documented. Incidentally, this question is flagged with the language-extension tag for a reason.Stereoisomerism
@CodeMaker: You can't document something that is undefined behavior, which is what the C++ specification says happens. Well, you could, but it would be useless documentation since it would change whenever you changed compilers. Or the phase of the moon. Or if a stiff breeze blew through the room. It's like asking what the behavior of accessing a deallocated piece of memory is.Cuttle
@NicolBolas True. And that proves we have gone beyond the scope of general reference. The longjmp still exists to be used, but the undocumented nature of its riskiness impels me to ask the question of what circumstances might non-intuitively cause problems and what considerations should be made to use it relatively safely.Stereoisomerism
B
4

You'll get plenty of haterade about using goto at all. Normally I'd jump right on the bandwagon, but in this particular case it sounds more like code golf to me. So here you go.

Use goto to move the instruction pointer to a "label" in your code, which is a C++ identifier followed by a colon. Here's a simple example of a working program:

#include <iostream>
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    int i = 0;
step:
    cout << "i = " << i;
    ++i;
    if( i < 10 )
        goto step;

}

In this case, step: is the label.

There are concerns about context.

  • You can only goto to a label within the current function.
  • If your goto skips the initialization of a variable, you may evoke Undefined Behavior (Code which will compile, but you can't say for sure what it will actually do.).
  • You cannot goto in to a try block or catch handler. However, you can goto out of a try block.

You "can goto" with pointers etc provided the other concerns are met. If the pointer in question is in-scope at the call site and in-scope at the branch site, no problem.

Baugh answered 28/9, 2011 at 19:12 Comment(4)
Thanks. And I think you might have gotten me wrong here. What I meant to ask is "Can you have jump labels as pointers, arrays, or vectors for the purposes of the goto statement?"Stereoisomerism
OP says: "I don't usually code C++". Maybe expand "UB" acronym to "undefined behavior", or give a brief definition.Cardiomegaly
@Code: You mean you want to store jump labels in a vector, for example?Baugh
@JohnDibling, by the way, do you know if a GCC void pointer label will do anything to these limits?Stereoisomerism
D
3

I think this reference has most of the information you are looking for.

goto

longjmp

Despoliation answered 28/9, 2011 at 19:1 Comment(1)
I wouldn't call MSDN "the" reference, rather "a" reference :) (It states: "Describes the C++ programming language as implemented in Microsoft C++.")Bower
B
3

computed goto --> switch

Really, they share a (common, but not universal) underling implementation as a jump table.

Boles answered 28/9, 2011 at 23:2 Comment(3)
Only sometimes, if a switch has only a few choices then it will most likely be implemented as a series of if / else if statements instead.Fulbert
Sure, and the compiler could choose the same implementation for a computed goto.Boles
A switch statement only constitutes a forward jump. I could approximate the computed goto by doing a computed_goto: switch (goto_variable) { ... } before so I could do goto_variable = 5; goto computed_goto; but I'm hoping to use the longjmp() here. I remember doing that with Java though, only using a labelled while(true) loop and continue instruction instead, but alas Java isn't as Duff's device friendly.Stereoisomerism
B
1

If I understand the original question, the question is actually an interesting one. Rewording the question (to what I think is an equivalent question): "How do you do a FORTRAN computed goto in C?"

First we need to know what a computed goto is: Here is a link to one explanation: http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0124.htm.

An example of a computed GOTO is:

    GO TO (12,24,36), INDEX

Where 12, 24, and 36 are statement numbers. (C language labels could serve as an equivalent, but is not the only thing that could be an equivalent.)

And where INDEX is a variable, but could be the result of a formula.

Here is one way (but not the only way) to do the same thing in C:

int SITU(int J, int K)
{
int raw_value = (J * 5) + K;

int index = (raw_value % 5) - 1;

return index;
}


int main(void)
{
int J = 5, K= 2;

// fortran computed goto statement: GO TO (320,330,340,350,360), SITU(J,K) + 1
switch (SITU(J,K) + 1)
{
case 0: // 320
    // code statement 320 goes here
    printf("Statement 320");
    break;
case 1: // 330
    // code statement 330 goes here
    printf("Statement 330");
    break;
case 2: // 340
    // code statement 340 goes here
    printf("Statement 340");
    break;
case 3: // 350
    // code statement 350 goes here
    printf("Statement 350");
    break;
case 4: // 360
    // code statement 360 goes here
    printf("Statement 360");
    break;
}

printf("\nPress Enter\n");
getchar();
return 0;
}

In this particular example, we see that you do not need C gotos to implement a FORTRAN computed goto!

Bathysphere answered 11/9, 2012 at 2:50 Comment(1)
Re your last sentence: But a switch statement is just an advanced (multi-target) form of goto.Ives
L
0

Longjmp can get you out of a signal handler which can be nice - and it'll add some confusion as it will not reset automatic (stack-based) variables in the function it long jumps to defined prior to the setjmp line. :)

Latish answered 28/9, 2011 at 19:7 Comment(2)
At the low low cost of completely undefined behavior in a lot of scenarios.Stevana
From all sounds of it he's trying to write complex code to win a bet - I would never touch goto or longjjmp in real code - they both are complex in the first place. :pLatish
K
0

There is a GCC extension called Labels as Values that will help you code golf, essentially giving you computed goto. You can generate the labels automatically, of course. You will probably need to do that since you can't know how many bytes of machine code each line will generate.

Kletter answered 27/9, 2012 at 20:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.