This is a perfectly valid program except:
- not declaring
p
as volatile
and
- declaring
argv
as char *
.
And yes, free()
needs to be called after longjmp()
if the memory has been allocated before longjmp()
.
Since it's guaranteed that the return value of setjmp
will be 0
on direct execution, we can be sure that memory will be allocated via case 0
.
And, if a local variable needs to be changed after setjmp()
and before calling longjmp
then you need to declare it as volatile
to ask compiler to not to optimize and store in registers but to store/load from stack only.
Why? Because when longjmp
loads the saved environment it loads program counter, stack pointer and values in registers saved at the time of direct setjmp()
call. If compiler optimizes and stores the variable in register after the setjmp()
call then longjmp
can't access that value since what it has is register values at the time of setjmp
call. So we ask compiler to not to save in registers but to save/load from stack only. And since longjmp
has stack pointer we get the latest values of accessible variables from the stack.
Updated code:
#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
jmp_buf jmpbuf;
volatile int *p;
switch (setjmp(jmpbuf)) {
case 0:
p = malloc(10 * sizeof(int));
printf("p = %p\n", (void *)p);
longjmp(jmpbuf, 1);
break;
default:
printf("p = %p\n", (void *)p);
free((void *)p);
}
return 0;
}