嵌套对象中的内存不可用

Memory not being free in nested objects

我发现来自 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;
}
ShoppingCart::ShoppingCart() {
    // Constructor
    items_in_cart = ItemSet();
}

最后一行可能行不通。赋值后,我们有两个 ItemSet 对象,它们具有相同的 items 值——在右侧创建的临时对象和 items_in_cart。当第二个被摧毁时,你有一个双倍的自由。

使用明智的方法收集对象,例如 std::liststd::vectorstd::array。否则,遵循rule of 3, rule of 5,否则为零。