1

I want to use longjmp to simulate goto instruction.I have an array DS containing elements of struct types (int , float, bool ,char). I want to jump to the place labled "lablex" where x is DS[TOP].int_val. how can I handle this?

sample code :

...
jmp_buf *bfj;
...
stringstream s;s<<"label"<<DS[TOP].int_val;
bfj = (jmp_buf *) s.str();
longjmp(*bfj,1);

but as I thought it's having problem what should I do?

error:

output.cpp: In function ‘int main()’:

output.cpp:101: error: invalid cast from type ‘std::basic_string, std::allocator >’ to type ‘__jmp_buf_tag (*)[1]’

angela
  • 99
  • 1
  • 1
  • 8
  • 2
    please think of people that want to help you. then reread the last statement. then provide all possible details. – Andrey Jun 21 '10 at 18:20
  • 5
    Using `longjmp` in C++ is not recommended, since it skips destructor. What is it you want to do with it? It's _very_ likely there's a better solution to this. – sbi Jun 21 '10 at 18:21
  • 1
    @sbi agree. even goto is less evil – Andrey Jun 21 '10 at 18:25
  • @sbi it's a dynamic calling.goto can't work,I guess.and I know it's not safe or etc but the format should be like this. – angela Jun 21 '10 at 18:31
  • related to http://stackoverflow.com/questions/1376085/c-safe-to-use-longjmp-and-setjmp – Sam Miller Jun 21 '10 at 18:38
  • 7
    Give us the big picture, we can't really help you otherwise. Not the small picture ("I want to longjmp"), the big one ("I think I need to longjmp because..."). I really doubt you need to do this. (In other words, stop telling us you *have* to do this. If you were in a position to make such claims, you wouldn't need our help.) – GManNickG Jun 21 '10 at 18:51

5 Answers5

6

You probably don't want to use longjmp at all but I hate it when people answer a question with "Why would you want to do that?" As has been pointed out your longjmp() usage is wrong. Here is a simple example of how to use it correctly:

#include <setjmp.h>

#include <iostream>

using namespace std;

jmp_buf jumpBuffer;  // Declared globally but could also be in a class.

void a(int count) {
  // . . .
  cout << "In a(" << count << ") before jump" << endl;
  // Calling longjmp() here is OK because it is above setjmp() on the call
  //   stack.
  longjmp(jumpBuffer, count);  // setjump() will return count
  // . . .
}


void b() {
  int count = 0;

  cout << "Setting jump point" << endl;
  if (setjmp(jumpBuffer) == 9) return;
  cout << "After jump point" << endl;

  a(count++);  // This will loop 10 times.
}


int main(int argc, char *argv[]) {
  b();

  // Note: You cannot call longjmp() here because it is below the setjmp() call
  //  on the call stack.

  return 0;
}

The problems with your usage of longjmp() are as follows:

  1. You don't call setjmp()
  2. You haven't allocated the jmp_buf either on the stack or dynamically. jmp_buf *bfj is just a pointer.
  3. You cannot cast a char * to jmp_buf * and expect it to work. C++ not a dynamic language it is statically compiled.

But really, it is very unlikely that you should be using longjmp() at all.

jcoffland
  • 5,238
  • 38
  • 43
  • 7
    Just to reiterate - since i think this is the main point that the OP is missing - to do a `longjmp` you first have to `setjmp`. In other words, you _cannot_ jump to a place you haven't been to before. – Tomer Vromen Jun 21 '10 at 20:23
5

The normal way to use longjump is incombination with setjump() as described here. You seem to want to make a jumptable as normally done with switch-case or with virtual functions.

Anyway, labels in code (compile-time) are not reachable with strings (run-time), so that is already your first problem. You would really need to find out the address of where you want to jump to and my best guess would be to put setjump()'s where your labels are.

stefaanv
  • 14,072
  • 2
  • 31
  • 53
  • would you plz explain more how should I do this? it's really confusing. – angela Jun 21 '10 at 18:42
  • We'd like to but you have yet to tell us what you're trying to do. – GManNickG Jun 21 '10 at 18:50
  • In short, with the setjump-function, you fill in an "environment". The return-value of setjump is 0, so you can check that you just did the setjump. With that envirenment, you can do a longjump, so the setjump() function will return with what the longjump has passed. If this sounds confusing, that's because it is. Better check alternatives before using it. I only so it used in an executer where it was used to break out and then resume at the breakpoint. – stefaanv Jun 21 '10 at 18:55
  • @GMan well I'm tring to say "GOTO WHERE THE LABEL IS label+DS[TOP].int_val". but goto doesn't work as I suppose.I'm simulating activation records where the return address is actually DS[TOP].int_val. – angela Jun 21 '10 at 19:13
  • @nagela: No, no. Not what you're trying to do on this tiny scale, the *big picture*. *Why* are you trying to use longjmp? (Remember, big picture answer! Not "to jump.") – GManNickG Jun 21 '10 at 19:25
2

You've totally failed C++. Firstly, goto's are bad, and not for the uninitiated- there's a reason that for, while, break, continue etc exist. Secondly, you're trying to convert a string into an identifier, which is impossible at runtime unless you code it yourself. Thirdly, you're.. trying to cast a const char* to a jmp_buf*? What?

In addition to that, C++ does have goto. But if you want to jump given an int, then you're going to have to switch it, e.g.

switch (DS[TOP].int_val) {
case 1:
    goto label1;
    break;
case 2:
    goto label2;
    break;
default:
    throw std::runtime_error("Unrecognized label!");
}
Puppy
  • 144,682
  • 38
  • 256
  • 465
  • so sorry to tell this that I HAVE TO USE GOTO & LONGJMP but no other choice. since it must be three address code,I can't use switch. but goto can't go in this situation because the address is dynamic. – angela Jun 21 '10 at 18:29
  • 4
    "You've totally failed C++" ??? Even if the OP has failed, it is better to state that in a way that isn't so antagonistic. – A. Levy Jun 21 '10 at 20:25
  • no it's nothing about c++, but for writing compilers you NEED to produce 3 address code.and it is near assembly language. that's why as I commented above I have to use goto and longjmp. – angela Jun 21 '10 at 23:14
0

Sounds like you want a function pointer:


((void(*)(void))*((int *)DS[TOP].int_val))();

This treats DS[TOP].int_value like an address and jumps to it. If you wanted to jump to where DS[TOP].int_value is located, you would:


((void(*)(void))*((int *)&DS[TOP].int_val))();

Either way, ugly, ugly code. But it should do what you want.

Michael Dorgan
  • 12,453
  • 3
  • 31
  • 61
  • This is a function call, so it can only jump to functions because a return is required. – stefaanv Jun 21 '10 at 18:57
  • You are reinterpreting an integer as a function and calling it...that is most likely going to crash your program, unless you are developing a buffer overrun exploit and you have specifically crafted that integer (and the data after it) to be valid code. – A. Levy Jun 21 '10 at 20:30
  • I have no idea where he's going - but you're right, this will place an extra return address on the stack and cause issues if he doesn't return. – Michael Dorgan Jun 21 '10 at 22:45
0

When setjmp() is called, the system effectively takes a snapshot of the call and parameter stack. This snapshot will remain valid until user code exits the block in which setjmp() was called; if longjmp() is called with that snapshot, execution will resume as though the setjmp() were returning for the first time, except that instead of returning zero, it will return the second parameter passed to longjmp(). It is very important to note that calling longjmp() with an invalid snapshot may have very bad effects. In some systems, such an invalid call may "seem" to work, but corrupt the system in such a way that it later crashes.

Although setjmp()/longjmp() are sometimes appropriate in pure C programs, having a C program call setjmp() to create a snapshot, and then call some C++ code which in turn calls longjmp() to return to that snapshot, is a recipe for disaster. Nearly all situations where one would want to do that may be better handled using exceptions.

supercat
  • 77,689
  • 9
  • 166
  • 211