GCC拡張のcleanup属性は大域脱出と共存できない【俺を信じろ】
GCC拡張のcleanup属性とは?
C言語でC++のRAII的なことができる。参照
大域脱出(nonlocal exit)とは?
C言語では、setjmp()
/ longjmp()
、略してsjljのこと。参照
大域(non-local)とはどういう意味?
コールスタックのフレームひとつが「ローカル」と考える。フレームにはローカル変数が入ってるし。
普通はreturn
で一つ根本方向のフレームに戻るだけだが、大域脱出では一つと言わず、いくつでも戻れる(戻らなくてもいい)。ゆえにnon-local。
コールスタックの根本方向に向かうということは、sjljは例外に似ている?
ある意味では似ている。致命的な違いは、スタックの巻き戻しを行わないこと。
行わせる方法はない。抜け道はない。俺を信じろ。
共存できないとは?
#include <stdio.h>
#include <setjmp.h>
#define _cleanup_(x) __attribute__((cleanup(x)))
#define _cleanup_free_ _cleanup_(freep)
static jmp_buf buf;
static void freep(void *p) {
printf("free!\n");
// free(*(void**) p);
}
static void foo(int jmp) {
_cleanup_free_ char *c_auto_free = NULL;
printf("Hello\n");
if (jmp) {
longjmp(buf, 1);
}
}
int main() {
foo(0);
if (!setjmp(buf)) {
foo(1);
}
printf("Out\n");
return 0;
}
#include <stdio.h>
#include <setjmp.h>
#define _cleanup_(x) __attribute__((cleanup(x)))
#define _cleanup_free_ _cleanup_(freep)
static jmp_buf buf;
static void freep(void *p) {
printf("free!\n");
// free(*(void**) p);
}
static void foo(int jmp) {
_cleanup_free_ char *c_auto_free = NULL;
printf("Hello\n");
if (jmp) {
longjmp(buf, 1);
}
}
int main() {
foo(0);
if (!setjmp(buf)) {
foo(1);
}
printf("Out\n");
return 0;
}
出力:
Hello
free!
Hello
Out
longjmp()でmain()に戻ったときには、freep()が実行されない。sjljはスタックの巻き戻しを行わないのでこうなる。
sjlj以外の方法は?
GCCのC言語には、sjlj以外の大域脱出の方法がない。ないったらない。俺を信じろ。
GCC拡張にはcleanup属性があるのに、なぜスタックの巻き戻しを行う大域脱出の方法がないのか? わからない。とにかく、ないものはない。俺を信じろ。
GCC以外なら?
WindowsのC言語には構造化例外(SEH)がある。もちろんMSVC限定、かと思ったら最近のMingwでも使えるらしい。
まとめ
これは、「プログラミング言語はみんな同じようなもの」と思ったら深刻に大間違いなケースのひとつ。大多数の言語でものすごく頻繁に使われている制御構造2つを同時には使えないのだ。「C言語(GCC)にはこういう制約がある」とよくよく体に染み込ませた上で設計しないと、大域脱出とスタックの巻き戻しの両方をうっかり使ってしまう。
そんな鍛え方をしたくない? 人がいない? じゃあC言語、もうやめたほうがいいな?
Author And Source
この問題について(GCC拡張のcleanup属性は大域脱出と共存できない【俺を信じろ】), 我々は、より多くの情報をここで見つけました https://qiita.com/hajimen/items/4f1ca431479e5db0ee7f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .