2016-02-12 3 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::vector, или std::array. В противном случае следуйте за rule of 3, правилом of 5 или с нулем.

+0

Вы правы. Не нужно было иметь items_in_cart = ItemSet(). Это создало бы второй объект ItemSet. – superflux

+0

@superflux Это произойдет * в любое время * вы назначаете объект ItemSet или объект ShoppingCart. И это что-то, что действительно легко сделать случайно. Вот почему существует правило «Три правила», а также одна причина, по которой существуют встроенные классы контейнеров. – immibis