0

次のクラスであるmapPixelの概念を使用して、マップグリッド(2D離散数のポイント)を作成しています。

class MapPixel
{
    friend class Map;
protected:
    int x;
    int y;
    float height;
    float vegetation;

    std::vector<const MapPixel*> neib;
...methods declaration, default constructor/destructor

ここで、neibは、thenに隣接する他のMapPixelへのポインタのリストです。

私はこの方法を使用しています

void MapPixel::addNeib(const MapPixel* neib_)
{
    neib.push_back(neib_);
}

グラフを作成するためにネイバーピクセルへのポインタを追加します(境界線は中央のピクセルよりもネイバーが少ないため、このリストはサイズに依存します)。

私の手順は、メンバーでクラスマップを作成することです

MapPixel **pixels;

コンストラクターでMap::Map()を使用して

pixels = new MapPixel*[width];
for (int i = 0; i < width; i++)
    pixels[i] = new MapPixel[height];

MapPixel :: addNode()メソッドを使用してネットワークを構築します(例)

pixels[i][j].addNeib(&pixels[i][j+1]);

そして、Map ::〜Map()で、逆の順序でMapPixelを削除します(ダブルフリーを回避するためにneibsを削除せずに):

for (int i = 0; i < width; i++)
    delete pixels[i];
delete pixels;

Valgrindは、次のような大きなメモリリークがいくつかあると言います。

2,509,088 bytes in 39,205 blocks are possibly lost in loss record 4,071 of 4,071
  in MapPixel::addNeib(MapPixel const*) in Source/mappixel.cpp:52
  1: malloc in vg_replace_malloc.c:266
  2: operator new(unsigned long) in /usr/lib/libstdc++.6.0.9.dylib
  3: __gnu_cxx::new_allocator&lt;MapPixel const*&gt;::allocate(unsigned long, void const*) in ...
  4: std::_Vector_base&lt;MapPixel const*, std::allocator&lt;MapPixel const*&gt; &gt;::_M_allocate(unsigned long) in stl_vector.h:131
  5: std::vector&lt;MapPixel const*, std::allocator&lt;MapPixel const*&gt; &gt;::_M_insert_aux(__gnu_cxx::__normal_iterator&lt;MapPixel const**, std::vector&lt;MapPixel const*, std::allocator&lt;MapPixel const*&gt; &gt; &gt;, MapPixel const* const&amp;) in vector.tcc:271
  6: std::vector&lt;MapPixel const*, std::allocator&lt;MapPixel const*&gt; &gt;::push_back(MapPixel const* const&amp;) in stl_vector.h:608
  7: MapPixel::addNeib(MapPixel const*) in mappixel.cpp:52

すべて52行目に関連しています:

neib.push_back(neib_);

誰かがこれを理解していますか?std::vectorを使用してピクセルのネイブを構築できるかどうかについて自信を失いました。

4

2 に答える 2

1

valgrindは、「完全に失われた」ではなく、「おそらく失われた」と言っていることに注意ください。違いは重要です。正確な意味については、こちらをご覧ください。

そのエラーは、vector<>実装コードによって割り当てられたブロックに関するものであり、成長するにつれて要素を含むメモリのブロックのサイズを変更する可能性が最も高くなりvectorます。MapPixelのインスタンスを割り当てて解放するのを忘れた場合、これらを取得する可能性があります。これは、包含vectorによってメモリを解放できなくなるためですが、独自のコードに関するエラーも発生します。

そうでもなければ!pixelsアレイを解放するとき、使用していますdelete[]delete

更新:を使用していますdelete。を使用する必要がありますdelete[]。これは確かにメモリリークです。割り当てたものはすべて、new[]で解放する必要がありますdelete[]。そうしないと、適切なデストラクタ(コンパイラによって自動的に生成されたものでも)が最初の要素に対してのみ呼び出されます。

于 2012-05-06T08:22:52.353 に答える
0

deleteすでに述べた他の答えと同様に、メモリリークは間違ったオペレータが原因である可能性があります。コンストラクターでは、演算子new []を使用して配列の配列を作成します:

pixels = new MapPixel*[width];
for (int i = 0; i < width; i++)
  pixels[i] = new MapPixel[height];

対応する配列削除演算子delete[]を使用して、配列のメモリを解放する必要があります。

for (int i = 0; i < width; i++)
  delete [] pixels[i];
delete [] pixels;

std::vectorただし、代わりにピクセルマトリックスにネストを使用することをお勧めします。このようにして、メモリ管理を無料で利用できます。

std::vector<std::vector<MapPixel> > pixels;
// in constructor something like:
pixels.resize(width, std::vector<MapPixel>(height));
// nothing to do in destructor

あなたの隣人のために、私はstd :: vectorを使用しませんが、プレーンMapPixel *neib[8];(ムーア近傍を想定)またはむしろを使用しstd::array<MapPixel*, 8> neib;ます。しかし、私はあなたがこのアイテムにどんな他の要件を持っているかもしれないかわかりません。

メモリ管理に加えて、STLコンテナーを使用すると、他の利点も得られます。たとえば、便利なメンバー関数は、ほんの数例を挙げると、ポインターに減衰しません。

于 2012-05-06T18:50:25.297 に答える