2016-02-12 50 views
0

我发现这个Valgrind引起内存错误的内存泄漏:无效的free()/ delete/delete []/realloc()。嵌套对象中的内存不空闲

==7367== Invalid free()/delete/delete[]/realloc() 
==7367== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7367== by 0x40077F: ItemSet::~ItemSet() (cart.cpp:33) 
==7367== by 0x40086B: ShoppingCart::~ShoppingCart() (cart.cpp:14) 
==7367== by 0x400828: main (cart.cpp:45) 
==7367== Address 0x5a1c0b0 is 0 bytes inside a block of size 40 free'd 
==7367== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7367== by 0x40077F: ItemSet::~ItemSet() (cart.cpp:33) 
==7367== by 0x400800: ShoppingCart::ShoppingCart() (cart.cpp:39) 
==7367== by 0x400817: main (cart.cpp:43) 
==7367== 
==7367== 
==7367== HEAP SUMMARY: 
==7367==  in use at exit: 40 bytes in 1 blocks 
==7367== total heap usage: 2 allocs, 2 frees, 80 bytes allocated 
==7367== 
==7367== LEAK SUMMARY: 
==7367== definitely lost: 40 bytes in 1 blocks 
==7367== indirectly lost: 0 bytes in 0 blocks 
==7367==  possibly lost: 0 bytes in 0 blocks 
==7367== still reachable: 0 bytes in 0 blocks 
==7367==   suppressed: 0 bytes in 0 blocks 
==7367== Rerun with --leak-check=full to see details of leaked memory 
==7367== 
==7367== For counts of detected and suppressed errors, rerun with: -v 
==7367== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 

这是代码。它是我的程序的简化版本,但它仍然存在我遇到的问题。

#include <cstdlib> 

class ItemSet { 
    private: 
     int* items; 

    public: 
     ItemSet(); 
     virtual ~ItemSet(); 

     // ItemSet Methods... 
}; 

class ShoppingCart { 
    private: 
     ItemSet items_in_cart; 
    public: 
     ShoppingCart(); 

     // ShoppingCart methods... 
}; 

ItemSet::ItemSet() { 
    // Constructor 
    int max_num_of_items = 10; 
    items = (int*)calloc(sizeof(int), max_num_of_items); 
} 

ItemSet::~ItemSet() { 
    // Destructor 
    if (NULL != items) { 
     // Frees the dynamically allocated register files 
     free(items); 
    } 
} 

ShoppingCart::ShoppingCart() { 
    // Constructor 
    items_in_cart = ItemSet(); 
} 

int main() { 
    ShoppingCart cart = ShoppingCart(); 

    return 0; 
} 
+3

可能重复的[三条法则是什么?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) –

+2

您正在实现一个管理资源的类,那么你不会正确管理资源,你不会实现复制构造函数和赋值。错误不是泄漏,它是双“免费”的。 – Niall

+0

这就是为什么你应该使用'std :: vector','std :: array'或其他一些明智的方法来创建一个集合。 –

回答

0
ShoppingCart::ShoppingCart() { 
    // Constructor 
    items_in_cart = ItemSet(); 
} 

最后一行不可能工作。在赋值之后,我们有两个ItemSet对象,其值为items的值相同 - 临时创建的右侧和items_in_cart。当第二个被破坏时,你有一个双倍免费。

使用一种明智的方法来收集诸如std::list,std::vectorstd::array之类的对象。否则,请按照rule of 3,规则of 5或零。

+0

你说得对。没有必要有items_in_cart = ItemSet()。这将创建第二个ItemSet对象。 – superflux

+0

@superflux这将发生*任何时候*你分配一个ItemSet对象或一个ShoppingCart对象。这是非常容易做到的事情。这就是三元规则存在的原因,也是内置容器类存在的原因之一。 – immibis