tags:

views:

143

answers:

5

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]’

+3  A: 

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!");
}
DeadMG
angela
"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
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
+4  A: 

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
would you plz explain more how should I do this? it's really confusing.
angela
We'd like to but you have yet to tell us what you're trying to do.
GMan
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
@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
@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.")
GMan
A: 
Michael Dorgan
This is a function call, so it can only jump to functions because a return is required.
stefaanv
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
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
+3  A: 

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
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
Excellent answer!
A. Levy
A: 

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