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 是指向其他 MapPixels 的指针列表,与 then 相邻。

我正在使用该方法

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

添加指向 neiber 像素的指针以构建图形(由于边界的 neibs 少于中心像素,因此此列表取决于大小)。

我的程序是有一个带有成员的类 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 来构建像素的 neibs 失去信心。

4

2 回答 2

1

请注意,valgrind 说“可能丢失”,而不是“肯定丢失”。区别很重要。有关确切含义,请参见此处

该错误与vector<>实现代码分配的块有关,最有可能随着vector增长而调整包含元素的内存块的大小。如果您正在分配实例MapPixel并忘记释放它们,您可能会得到这些,因为包含vector将无法释放其内存,但您也会收到有关您自己的代码的错误。

除非!当您释放pixels阵列时,您使用的是delete[]ordelete吗?

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

于 2012-05-06T08:22:52.353 回答
0

正如已经提到的另一个答案,内存泄漏很可能是由错误的delete运算符引起的。在构造函数中,您使用operator 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 回答