23

メッセージ:

terminate called after throwing an instance of 'std::bad_alloc'
what():  std::bad_alloc

私はgdbバックトレースを調べましたが、これは私が自分で実装した最低レベルのメソッドです。

/*
 * get an array of vec3s, which will be used for rendering the image
 */
vec3 *MarchingCubes::getVertexNormalArray(){
    // Used the same array size technique as getVertexArray: we want indices to match     up
    vec3 *array = new vec3[this->meshPoints.getNumFaces() * 3]; //3 vertices per face

    int j=0;
    for (unsigned int i=0; i < (this->meshPoints.getNumFaces() * 3); i++) {
        realVec normal = this->meshPoints.getNormalForVertex(i);
 //     PCReal* iter = normal.begin();

        if (normal.size() >= 3) {
            array[j++] = vec3(normal[0], normal[1], normal[2]);
        }
        cout << i << " ";
    }

    return array;
}

上記のcoutステートメントは、7000回以上の反復後に終了することを示しています。上記の関数は、アプリケーションの終わり近くで1回だけ呼び出されます。上記を呼び出す前に非常によく似た関数を呼び出しますが、問題は発生しません。

4

2 に答える 2

31

(コメントからの移動/拡張)

割り当てを解除せずに毎回新しいアレイを割り当てているため、大量のメモリリークが発生します。つまり、システムにメモリを返すことなく、システムにメモリを要求し続けます。最終的にヒープ上のスペースが終了し、次の割り当てで取得するのはstd::bad_alloc例外です。

「Cスタイル」の解決策は、そのようなメモリが不要になったときに(を使用して)割り当てを解除することを忘れないことですdelete[]が、これは(1)エラーが発生しやすいです(たとえば、関数内に複数のリターンパスがある場合を考えてください)。 (2)潜在的に例外が安全ではありません(例外がある場合、すべての命令が潜在的なリターンパスになります!)。したがって、この方法は避ける必要があります。

慣用的なC++ソリューションは、スマートポインター(ポインターをカプセル化し、破棄されたときに関連するメモリの割り当てを解除する小さなオブジェクト)、またはほぼ同じことを行うがコピーセマンティクスといくつかのベルとホイッスルを備えた標準コンテナーのいずれかを使用することです(それらの中に配列のサイズを格納することを含む)。

于 2011-12-04T21:57:23.530 に答える
3

this->meshPoints.getNormalForVertex(i)私の問題は、長さが。未満の配列(またはベクトル、思い出せない)にアクセスすることであることが判明しましたthis->meshPoints.getNumFaces() * 3。それで、それは範囲外にアクセスしていました。

于 2011-12-06T08:44:18.463 に答える