0

何らかの理由で、「i got here」が表示される前に次のプログラムがクラッシュします。try-catch 部分をコメント アウトすると、プログラムが実行され、正常に終了します。

#include <iostream>

int error_function () {

    throw 5;

    return 0;
}


int main () {

    double* b = new double[6];

    for (int i = 0; i < 6; i++) {
        b[i] = i;
    }

    double* c = new double(*b);

    for (int i = 0; i < 6; i++) {
        c[i] = i+1;
    }

    for (int i = 0; i < 6; i++) {
        std::cout << b[i] << " " << c[i] << std::endl;
    }

    try {
        error_function();
    }
    catch (int t) {
        std::cout << "catched an int: " << t << std::endl;
    }

    std::cout << "i got here" << std::endl;
    return 0;
}

これは、プログラムがクラッシュしたときに得られる出力全体です。

0 1
1 2
2 3
3 4
4 5
5 6
catched an int: 5
*** glibc detected *** ./main: free(): invalid next size (fast): 0x0000000001f22070 ***
======= Backtrace: =========
/lib/libc.so.6(+0x77806)[0x7f2b273a0806]
/lib/libc.so.6(cfree+0x73)[0x7f2b273a70d3]
./main[0x400d92]
(a bunch of stuff)
Aborted

なぜこれが起こっているのか分かりません。どんな助けでも大歓迎です!

4

3 に答える 3

7

c を割り当てたときに double を 1 つしか割り当てておらず、最初の要素の後に要素にアクセスして境界をオーバーランするため、クラッシュしています。この場合、例外が処理された後に何らかのクリーンアップが行われ、glibc が破損したメモリを検出したように見えます。

問題の行は次のとおりです。

double* c = new double(*b);

for (int i = 0; i < 6; i++) {
        c[i] = i+1;
}

*b (または必要に応じて b[0]) の値をコピーする新しい double を割り当てます。これは、b が単なるポインターであるため、逆参照によって配列をコピーするコピー コンストラクターが呼び出されないためです。

std::vector を使用すると、メモリの割り当てと割り当て解除が自動的に処理され、例外が安全になるため、使用することをお勧めします。error_functionあなたが処理しなかった例外をスローした場合でも、それは正しくクリーンアップされますが、あなたnewのメモリはそのままではありません。

技術的には未定義の動作であるため、何が起こる可能性があります。

于 2012-08-17T20:51:13.313 に答える
1

あなたの問題はここにあります:

double* c = new double(*b);

これは、1 つの double にスペースを割り当て、初期値 を与えていますb[0]。後でc[1]などに割り当てます。これは未定義の動作です。

于 2012-08-17T20:53:43.180 に答える
1

timans の回答に追加します。

プログラムがヒープ オーバーランを実行しています。

for (int i = 0; i < 6; i++) {
    c[i] = i+1;
}

double c[0] には、新しい double のアドレスと b[0] の値があります。ただし、c[1]、c[2]、.... プログラムに関連する他のシステム情報を上書きする可能性があり、動作が不確実になります。 .

この行を変更すると、プログラムは正常に動作するはずです

double* c = new double[6];
for (int i = 0; i < 6; i++) {
    c[i] = b[i]+1;
}

main から戻る前に delete[] を呼び出すことを忘れないでください。

于 2012-08-17T21:02:30.377 に答える