1

私はこれについて何時間も頭を悩ませてきました。XCode 5 で Mac OS X 10.8 を実行しています。次のエラーが表示されます。

malloc: *** error for object 0x1006487b8: incorrect checksum for freed object - object was            
probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug

残念ながら、object 0x1006487b8はこの時点で解放されており、私のデバッガーにはそこにあったものは記憶されていません。

問題は、エラーが同じ場所で発生しないことです。少しのメモリが適切に解放されておらず、コンピュータがそれを別の目的に使用しようとして混乱してしまうとしか思えません。

私のコードは SDL 2 を使用しており、私が知る限りfree、次のような形式の関数呼び出しのみが発生しますrealloc

static LGC_Gate* LGC_CreateEmptyGate(){
    if (!gates) {
        gates = malloc(sizeof(LGC_Gate));
        if (!gates)
            return NULL;
    }
    else{
        LGC_Gate* tmpgates = realloc(gates, sizeof(LGC_Gate) * (numgates + 1));
        if (tmpgates)
            gates = tmpgates;
        else
            return NULL;
    }
    numgates++;
    gates[numgates - 1].id = numgates - 1;
    return &(gates[numgates - 1]);
}

gatesゲートの配列への静的なファイル スコープ ポインターであり、ファイルの先頭でそのように宣言されます。

static LGC_Gate* gates = NULL;
numgatesファイルの先頭でゼロに初期化され、現在使用中のゲート数を表します。gatesサイズは常に である必要がありますnumgates * sizeof(LGC_Gate)

私の計画は、ユーザーが作成したすべてのゲートを単一の配列に保持することでした。これにより、簡単にそれらを集計して、すぐに取得できるようになりました。このLGC_CreateEmptyGate関数は、たとえば次のように使用されます。

LGC_Gate* LGC_InitActGate(LGC_Action act, uint8_t innum, uint8_t outnum){
    LGC_Gate* product = LGC_CreateEmptyGate();
    if (!product)
        return NULL;

    product->rule.type = LGC_FUNCTION;
    product->rule.act = act;

    product->input.used = innum;
    product->input.val = 0;
    product->output.used = outnum;
    product->output.val = 0;

    int i;
    for (i = 0; i < 8; i++) {
        product->inputfrom[i].active = 0;
    }

    return product;

}

私はひどく間違ったことをしましたか?

アップデート

次のコードを使用してデバッグを行いました。

printf("%d\n", sizeof(LGC_Gate));
LGC_Gate* TestGates[5];
//Go through the gates, initialize each of them, record the value of their ptr,
//and if any are LESS than sizeof(LGC_Gate) apart, report an error.
int gcount;
for (gcount = 0; gcount < 5; gcount++) {
    TestGates[gcount] = LGC_InitActGate(LGC_NOR, 2, 1);
    printf("%p\n", TestGates[gcount]);
    if (gcount < 4) {
        if (TestGates[gcount] + sizeof(LGC_Gate) > TestGates[gcount + 1]) {
            printf("Error!");
            //TestGates[gcount + 1]->id = 4;  If this line were uncommented, 
            //                                BAD_ACCESS ensues.          
        }
    }
}

驚いたことに、これは実際にはエラーを出力し、実際にいくつかのポインターでクラッシュします。訂正: エラー ポインターは常に 3 番目のポインターのようです。LGC_InitActGate一度呼び出すLGC_InitEmptyGateと、残りの期間は単にデータをコピーすることに注意してください。何が起こっている?

更新 2

さて、私は今エラーを発見したと思います。realloc が呼び出されるたびに、メモリのブロック全体が再配置される場合と再配置されない場合があります。これにより、以前の解放されたメモリを指している無用の 5 つのポインターの配列がレンダリングされます。これは完全に理にかなっていますが、これは 1 つのとんでもないバグです。前に気づいていたはずです。これを修正する方法はわかりませんが、助けてくれてありがとう。

4

3 に答える 3

1

このエラーは、システムがメモリを割り当てようとしているが、空きプールに移動したときに、次に使用可能なブロックが破損しているように見えることを示しています。

void* p = malloc(100);
free(p);
strcpy(p, "How do you like these apples, malloc?";
p = malloc(100); // <-- crash may happen here, depending on how the free list works.

通常、クラッシュの場所は単なる検出であり、原因ではありません。

このようなクラッシュを追跡できる 1 つの方法は、アドレスのデータを調べることです (運が良ければ、文字列や既知の値などの認識可能なものを取得できます)。

それ以外の場合は、valgrind を打ち破る時が来ました。

于 2013-10-24T04:50:24.980 に答える