Does setjmp literally save the state of the program?
No, setjmp() saves some CPU register values as well as some context to allow the program to resume execution at the same place under a very strict set of conditions.
Note that you do not allocate enough memory for a struct str: you pass sizeof(str), which is the size of the str pointer. You should write this instead:
struct *str = malloc(sizeof(*str));
Futhermore, you cannot initialize str->s with an assignment, you should define the str member as a const char * instead of an array.
So, if I were to malloc 500 bytes, then use setjmp to save the state, then free the 500 bytes, then longjmp, would I be able to access those 500 bytes?
No, your program has undefined behavior because the memory block allocated by malloc and pointed to by str has been freed, thus str must not be dereferenced any longer.
Note that the last 2 statements in the main function will never execute because longjmp() does not return, it makes the program resume execution at the place where setjmp() returns and it makes setjmp return the value of the second argument passed to longjmp() (and the value 1 if 0 is passed for this argument).
Here is a modified version for illustration:
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
jmp_buf buf;
struct str {
const char *s;
int a;
};
int main() {
struct str *str = malloc(sizeof(*str));
str->s = "the string";
str->a = 31;
int res = setjmp(buf);
if (res == 0) {
printf("res: %d, str: %p, s: %s, a: %d\n",
res, (void *)str, str->s, str->a);
free(str);
str = NULL;
printf("str: %p\n", (void *)str);
longjmp(buf, 0);
} else {
printf("res: %d, str: %p\n", res, (void *)str);
if (res < 10)
longjmp(buf, res + 1);
}
return 0;
}
Output (compiled with optimisations):
res: 0, str: 0x7fe44de00000, s: the string, a: 31
str: 0x0
res: 1, str: 0x7fe44de00000
res: 2, str: 0x7fe44de00000
res: 3, str: 0x7fe44de00000
res: 4, str: 0x7fe44de00000
res: 5, str: 0x7fe44de00000
res: 6, str: 0x7fe44de00000
res: 7, str: 0x7fe44de00000
res: 8, str: 0x7fe44de00000
res: 9, str: 0x7fe44de00000
res: 10, str: 0x7fe44de00000
Output (compiled with -O0):
res: 0, str: 0x7ff4885000e0, s: the string, a: 31
str: 0x0
res: 1, str: 0x0
res: 2, str: 0x0
res: 3, str: 0x0
res: 4, str: 0x0
res: 5, str: 0x0
res: 6, str: 0x0
res: 7, str: 0x0
res: 8, str: 0x0
res: 9, str: 0x0
res: 10, str: 0x0
As you can see, what gets preserved by setjmp() is difficult to predict so this function must be used with extreme caution in circumstances where the programmer is well aware of the compiler behavior and only for very specific needs.