内存泄漏(Valgrind)在点网格上

时间:2012-05-06 08:00:40

标签: c++ memory-leaks valgrind

我正在使用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是指向其他MapPixel的指针列表,与之相邻。

我正在使用方法

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

添加一个指向neiber像素的指针来构建图形(因为边框的neib比中心像素少,这个列表与尺寸有关)。

我的程序是拥有一个带有成员的类Map

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来构建像素的neib失去了信心。

2 个答案:

答案 0 :(得分:1)

请注意,valgrind说“可能丢失”,而不是“肯定丢失”。差异很重要。请参阅here了解确切含义。

该错误是关于vector<>实现代码分配的块,最有可能在vector增长时调整包含元素的内存块的大小。如果你要分配MapPixel的实例并忘记释放它们,你可能会得到这些,因为包含vector然后无法释放它的内存,但是你也会得到关于你自己的代码的错误

除非!当您释放pixels数组时,您使用的是delete[]还是delete

更新:您正在使用delete。您需要使用delete[]。这确实是内存泄漏。使用new[]分配的任何内容都必须使用delete[]释放,否则只会为第一个元素调用正确的析构函数(即使是由编译器自动生成的析构函数)。

答案 1 :(得分:0)

正如已经提到的另一个答案,内存泄漏很可能是由错误的delete运算符引起的。在构造函数中,使用operator new[]创建一个数组数组:

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

您需要使用相应的array-delete operator 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容器还可以为您带来其他好处,例如方便的成员函数,它们不会衰减到指针,仅举几例。