3

これが私のコードです:

bool func(const MY_STRUCT *const ptr, some_struct *x, int y)
{
    printf("IN: %p\n", ptr); // ok
    for (int i = 0; i < y; ++i) {
        if (ptr->foo(x[i].key) == 0) {
            return false;
        }
    }
    printf("OUT: %p\n", ptr); // ok
    return true;
}

void process(void)
{
    ... ...
    for (i = 0; i < num; ++i) {
        MY_STRUCT *ptr = obj->GetPtr(); // success
        printf("BEFORE: %p\n", ptr); // ok
        if (func(ptr, x, y) == false) {
            continue;
        }
        printf("AFTER: %p\n", ptr); // <nil> when compile with -O2
        printf("%s", ptr->data); // *** segment fault here ***
    }
}

出力:

BEFORE: 0x0612d3fa
IN: 0x0612d3fa
OUT: 0x0612d3fa
AFTER: <nil>
segment fault

上記のコードを-O0でコンパイルすると、すべて正常に動作します。ただし、-O2を使用してコンパイルすると、関数funcが呼び出された後、ptrbecome NULL

これはgccのバグですか?誰かが同様のバグに遭遇したことがありますか?

私のgccバージョンは次のとおりです。gcc version 3.4.5 20051201 (Red Hat 3.4.5-2)

4

2 に答える 2

1

コンパイラにバグがある場合とない場合がありますが、投稿したコードに説明されている問題が見られる場合は、GCCが最適化レベルで壊れています。

問題のあるコード行には絶対に到達しないでください。

func常にtrueを返し、trueを返す場合、ループ本体の最後の部分はスキップされます。

コンパイラのバグが疑われる場合は、それを再現するコードサンプルを作成することから始めます。

実際のコードがどのように見えるかわからない場合、GCCの動作が正しいかどうかを推測することは不可能です。

于 2011-10-28T12:40:19.387 に答える
1

にスタックマッシャーがあり、呼び出し元のスタックfuncを上書きしている可能性があります。ptr配列または構造体へのアクセスがfunc範囲内にあることを確認してください。gcc 3.xの酸っぱい思い出がなかったら、これはほぼ間違いなく実際に起こっていることだと思います。それでも、これが最も可能性の高い説明です。

その点に関する疑問の恩恵をあなたに与えると、あなたのコードが本当にあなたの質問に投稿された通りであるなら、そうです、これはコンパイラのバグかもしれません

    printf("BEFORE: %p\n", ptr); // ok
    if (func(ptr, x, y)) {
        continue;
    }
    printf("AFTER: %p\n", ptr); // <nil> when compile with -O2

ptrは値によってに渡されるfuncため、。内で何が起こっても、呼び出し元の関数の値は変更されませんfunc

ただし、本当に古いコンパイラを使用しています。このバグを報告しても、何も起こりません。これを引き起こしたものは何でも、で変更されてから長い間である可能性が非常に高いですgcc。新しいバージョンまたは別のコンパイラを試してください。

于 2011-10-28T12:40:58.403 に答える