setjmp/longjmpとローカル変数

call/ccが出てきたので、ついでに:

#include <setjmp.h>

int main() {
  int x, y;
  jmp_buf k;

  x = 123;
  y = setjmp(k);
  if (y == 0) {
    x = 45;
    longjmp(k, 1);
  }
  return x + y;
}

はいくつを返すか、という話。

> gcc jmp.c -o jmp
> ./jmp
> echo $status
46
> gcc -O3 jmp.c -o jmp
> ./jmp
> echo $status
124

xにvolatileをつけ忘れると、こういうこと↑になります…

Cf.

> (let ((x 123))
    (let ((y (call-with-current-continuation
	      (lambda (k)
		(set! x 45)
		(k 1)))))
      (+ x y)))
46
- let val x = ref 123
=     val y =  
=         SMLofNJ.Cont.callcc
=         (fn k =>
=             (x := 45;
=              SMLofNJ.Cont.throw k 1))
= in
=     !x + y
= end;
val it = 46 : int