0
#include <setjmp.h>
#include <stdio.h>

jmp_buf jmp;

int test() {
    setjmp(jmp);
    puts("Birds are crying");
    return 0;
}


int main() {
    longjmp(jmp,1);
    return 0;
}

Above code doesn't work and crashes, why?

I am using the GCC compiler on Windows 10 Pro.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128

1 Answers1

3

Your usage of longjmp() is invalid, take a look at the documentation:

longjmp() restores the environment saved by the last call of setjmp()

You need to call setjmp() first in order to "set" where to jump before calling longjump(). That's why your code doesn't work. It's undefined behavior at best.

In other words, you cannot just use longjmp() as a simple "jump to global label". It has a different purpose.


after putting test(); call before the line longjmp it works and print it twice but why does it still crashes?

Let's again take a look at the documentation:

setjmp() saves the stack context/environment in env for later use by longjmp(). The stack context will be invalidated if the function which called setjmp() returns.

You cannot longjmp() to a buffer that was previously set by a function that has now returned. It's invalid. Your usage of setjmp()/longjmp() is really not what those functions are meant for.


Jumping out to another function isn't really the purpose of setjmp()/longjmp(), their purpose is to save the context and "jump back" to a function that has still not returned (see below example). It's not simple to come up with a meaningful example usage of such functions, since they are meant for advanced usage.

Here's a correct usage example (while still not that meaningful) from Wikipedia:

#include <stdio.h>
#include <setjmp.h>

static jmp_buf buf;

void second() {
    printf("second\n");         // prints
    longjmp(buf,1);             // jumps back to where setjmp was called - making setjmp now return 1
}

void first() {
    second();
    printf("first\n");          // does not print
}

int main() {   
    if (!setjmp(buf))
        first();                // when executed, setjmp returned 0
    else                        // when longjmp jumps back, setjmp returns 1
        printf("main\n");       // prints

    return 0;
}
Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • i call it on test function – soldier captain Nov 03 '20 at 16:59
  • 1
    Yes but test function is not called at all. – Rachid K. Nov 03 '20 at 16:59
  • 1
    @soldiercaptain yes, but you are not calling the test function, so that `setjmp()` is never called. – Marco Bonelli Nov 03 '20 at 16:59
  • after putting test(); call before the line longjmp it works and print it twice but why does it still crashes? – soldier captain Nov 03 '20 at 17:01
  • 1
    It still crashes because additionally, the jump buffer initialized via `setjmp()` becomes invalid after the function call in which the `setjmp()` was performed returns. Which means, among other things, that there is no defined way to use `longjmp()` to jump from (the initial execution of) `main()` to any other function. – John Bollinger Nov 03 '20 at 17:06
  • so i can't make my code work here ? because i was using goto and someone told me that i should use longjmp for going to a code outside the function – soldier captain Nov 03 '20 at 17:13
  • This answer cites Linux documentation, but the question states OP is using GCC on Windows. – Eric Postpischil Nov 03 '20 at 17:14
  • 1
    @EricPostpischil GCC on Windows == Cygwin/MinGW == GNU standard. `setjmp`/`longjmp` are C89, those links are just some of many that describe their usage. – Marco Bonelli Nov 03 '20 at 17:17
  • @EricPostpischil `setjmp`/`longjmp` work seemlessly even with the not very well conforming Microsoft C compiler. – Jabberwocky Nov 03 '20 at 17:18
  • 1
    @soldiercaptain updated with a working example, jumping out to another function isn't really the purpose of `setjmp`/`longjmp`, the purpose is to "jump back" to a function that has still not returned. – Marco Bonelli Nov 03 '20 at 17:22
  • @MarcoBonelli: Yes, `setjmp` and `longjmp` are specified in the C standard, so cite that, instead of Linux documentation. The fact that some routine appears in the C documentation and in Linux documentation does not mean it behaves the same way in general C implementations as it does in Linux implementations, and engineers need to learn to use documentation appropriate to their target, not the result of whatever Google search happens to match some keywords. – Eric Postpischil Nov 03 '20 at 17:31
  • 1
    @EricPostpischil OP is using GCC on Windows (which again, means Cygwin/MinGW), documentation links I provided very well apply to GCC. Linking to the standard instead of a manual page that conforms to the standard is just making things more complicated than they should for a newbie. That's why I prefer `linux.die.net`/`man7.org` links. – Marco Bonelli Nov 03 '20 at 17:40