2012-05-06 100 views
0

我创建使用mapPixel方式的概念的图格(点的2D离散数),一类:内存泄漏(Valgrind的)

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的指针。

我使用的方法

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

的指针添加到neiber像素构建的曲线图(因为边界具有比中心像素少neibs,该列表尺寸依赖)。

我的做法是有一类地图使用

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

我使用的方法MapPixel :: ADDNODE()在构造函数中地图成员

MapPixel **pixels; 

::地图()建立网络(例如)

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。

+0

在内存泄漏的可能出现的问题,你应该给我们俩如何页头(新),以及如何你的dealloc(删除)......这里部分缺失。例如。你以相反的顺序删除MaxPixel,好吧;但你是否是像素本身?我想答案是肯定的,而且给出的答案适用。尽管如此,让全新的/删除代码来看看会更好! – ShinTakezou

+0

添加了删除代码。我说的不是因为这个,因为Valgrind并没有抱怨新像素/新像素[我],所以我认为这个问题不在那里。 –

+1

应该不是'delete []'而是? – ShinTakezou

回答

1

请注意,valgrind表示“可能丢失”,而不是“肯定丢失”。差异很重要。具体含义见here

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

除非!当您释放pixels阵列时,您使用的是delete[]还是delete?您正在使用delete。您需要使用delete[]。这确实是一个内存泄漏。您使用new[]分配的任何内容必须与delete[]一起释放,否则只会为第一个元素调用正确的析构函数(即使是由编译器自动生成的析构函数)。

+0

+1有关像素的问题...刚完成评论关于缺乏细节... :) – ShinTakezou

+0

添加了代码,我删除像素。 –

0

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

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

您需要使用相应的释放为阵列存储阵列删除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容器为您提供了其他好处,例如方便的成员函数,他们不腐烂的指针,只是仅举几例。

+0

“(因为边界比中心像素少neibs,这个列表取决于大小)”这就是为什么我没有使用MapPixel * neib [8]。此外,分配只在开始时分配,std :: vector是常量访问。关于答案,我会检查它是否修复错误。 –

+1

@JCLeitão全息你获得一些[局部性](http://en.wikipedia.org/wiki/Locality_of_reference),即用于该阵列的存储器被直接集成在对象本身,而对于向量元素的存储器位于别处在堆上。但考虑到这些事情可能更像是过早优化。 – moooeeeep

+0

可能丢失2,509,088个字节我认为为代码添加熵尚不成熟... xD –