恐怖! 64bitと0と可変長引数の組み合わせ

32bit用に書かれたC++のプログラムを
64bit環境で動かそうとした時にハマったのでメモ。

void GetParam(const char* key, int size, ...) { ... for (int i = 0; i < size; ++i) { int* var = va_arg(va, int*); if (var) *var = values[i]; } ... } ... GetParam("foo", 4, &bar, 0, &baz, 0); // ここでsegmentation fault ...

上記のプログラムを動かしたらsegmentation faultで死んでしまいました。
if (var) *var = values[i]; のあたりが怪しいと目星をつけて調べてみると、
なんということでしょう。varの値が0であると期待している箇所で、
0x7fffffff00000000といういかにも怪しい値が入っていました。

恐らく、可変長引数を使っているため、コンパイラは引数の型が分からず、
0を32bitの整数として扱ってしまったのでしょう。
0をNULLに書き換えたら無事動きました。

「C++ではNULLと0は等価」だと思っていたのですが、
少なくても可変長引数が絡んでくる場合は異なるようです。恐ろしや。

2 Responses to “恐怖! 64bitと0と可変長引数の組み合わせ”

  1. たけおか より:

    呼出側のNULLの書き方が悪かったんでしょ。ふつーすぎる。

  2. Egtra より:

    現在のC++ならnullptrキーワードがベストというゴタクはさておき、使ったコンパイラはGCCですよね?
    GCCでは、NULLマクロの結果がポインタと同じサイズになるよう、こういう小細工が仕掛けられています。
    http://www.wdic.org/w/TECH/__null

Leave a Reply