10

私は g++ 4.8.3 のバグに遭遇したとほぼ確信していましたが、setjmp/longjmp の経験がほとんどないため、最初にこのリストを尋ねようと思いました。問題のコードを次の foo.cxx に単純化しました。

#include <setjmp.h>
#include <string.h>

// Changing MyStruct to be just a single int makes the compiler happy.
struct MyStruct
{
    int a;
    int b;
};

// Setting MyType to int makes the compiler happy.
#ifdef USE_STRUCT
typedef MyStruct MyType;
#elif USE_INT
typedef int MyType;
#endif

void SomeFunc(MyType val)
{
}

static void static_func(MyType val)
{
    SomeFunc(val);
}

int main(int argc, char **argv)
{
    jmp_buf env;
    if (setjmp(env))
    {
        return 1;
    }

    MyType val;
#ifdef USE_STRUCT
    val.a = val.b = 0;
#elif USE_INT
    val = 0;
#endif
    // Enabling the below memset call makes the compiler happy.
    //memset(&val, 0, sizeof(val));

    // Iterating 1 or 2 times makes the compiler happy.
    for (unsigned i = 0; i < 3; i++)
    {
        // calling SomeFunc() directly makes the compiler happy.
        static_func(val);
    }
    return 0;
}

このコードをコンパイルするには、g++ 4.8.3 を使用します。私にとって興味深いのは、USE_STRUCT を定義すると、コンパイルは失敗しますが、USE_INT では成功することです。コードには、USE_STRUCT でコンパイルを成功させる方法をさらに示すコメントがあります。g++ に -fPIC オプションを指定してもコンパイルが失敗するだけですが、これは私の環境では必須の引数です。

コンパイル エラーを確認するには:

g++ -DUSE_STRUCT -Wextra -Wno-unused-parameter -O3 -Werror -fPIC foo.cxx
foo.cxx: In function ‘int main(int, char**)’:
foo.cxx:26:5: error: variable ‘val’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Werror=clobbered]

ただし、単純な int を使用しても問題ありません。

g++ -DUSE_INT -Wextra -Wno-unused-parameter -O3 -Werror -fPIC foo.cxx

構造体の場合は val が破壊され、int の場合は破壊されない理由を説明してもらえますか? コード内のコメントに示されているように、構造体でコンパイルを成功させる他の方法についての洞察はありますか? それとも、これはコンパイラのバグを指していますか?

洞察やコメントは大歓迎です。

4

2 に答える 2