1

我正在尝试创建一个有点复杂的数据结构,这是一个简单的演示:

#include <iostream>
#include <vector>

struct Item;
struct Store;

struct globalEnviroment
{
     Item * data;
     globalEnviroment(Item * paramData) : data(paramData){}            
     ~globalEnviroment()
     {
        delete data;
     }
};

struct Item
{
        int id;
        std::vector<std::string>* names;

        Item() {};
        ~Item ( ) {delete names;}
};

int main ( )
{
    Item * items = new Item[3];
    items[0].names = new std::vector<std::string>();
    items[1].names = new std::vector<std::string>();
    items[2].names = new std::vector<std::string>();
    globalEnviroment * ge = new globalEnviroment(items);

    delete ge;

    return 0;
}

我越来越

munmap_chunk(): 无效指针

在线错误delete data;

我不确定删除 globalEnviroment 类型的对象的正确方法是什么。我的析构函数工作正常吗?

4

1 回答 1

1

你在globalEnviroment的析构函数中有两个问题

  • Item的定义是未知的,你编译的时候没有警告吗?
  • delete data;必须是delete [] data;(在当前情况下,您创建的实例给 i 参数的结果是 anew Items[...]而不是 的结果new Item

第一种可能性是将Item的定义移到 globalEnviroment的定义之前,同时更正 delete :

#include <vector>
#include <string>

struct Item
{
        int id;
        std::vector<std::string>* names;

        Item() {};
        ~Item ( ) {delete names;}
};

struct globalEnviroment
{
     Item * data;
     globalEnviroment(Item * paramData) : data(paramData){}            
     ~globalEnviroment()
     {
        delete [] data;
     }
};

int main ( )
{
    Item * items = new Item[3];
    items[0].names = new std::vector<std::string>();
    items[1].names = new std::vector<std::string>();
    items[2].names = new std::vector<std::string>();
    globalEnviroment * ge = new globalEnviroment(items);

    delete ge;

    return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ g++ -pedantic -Wall -Wextra c.cc
pi@raspberrypi:/tmp $ ./a.out

在valgrind下执行:

pi@raspberrypi:/tmp $ valgrind ./a.out
==13369== Memcheck, a memory error detector
==13369== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==13369== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==13369== Command: ./a.out
==13369== 
==13369== 
==13369== HEAP SUMMARY:
==13369==     in use at exit: 0 bytes in 0 blocks
==13369==   total heap usage: 6 allocs, 6 frees, 20,296 bytes allocated
==13369== 
==13369== All heap blocks were freed -- no leaks are possible
==13369== 
==13369== For counts of detected and suppressed errors, rerun with: -v
==13369== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

第二种可能性是将析构函数的定义移到Item的定义之后:

#include <vector>
#include <string>

struct Item;

struct globalEnviroment
{
     Item * data;
     globalEnviroment(Item * paramData) : data(paramData){}            
     ~globalEnviroment();
};

struct Item
{
        int id;
        std::vector<std::string>* names;

        Item() {};
        ~Item ( ) {delete names;}
};

globalEnviroment::~globalEnviroment()
{
  delete [] data;
}

int main ( )
{
    Item * items = new Item[3];
    items[0].names = new std::vector<std::string>();
    items[1].names = new std::vector<std::string>();
    items[2].names = new std::vector<std::string>();
    globalEnviroment * ge = new globalEnviroment(items);

    delete ge;

    return 0;
}

编译和执行给出相同的结果


从中

  • 在你的类中有指针,你必须处理赋值、复制构造函数等,你必须定义它们。
  • Item的构造函数不会将names初始化为NULL,如果不设置析构函数后的字段会有未定义的行为
  • 如果使用Items数组或仅使用Item初始化,则必须假设data ,但是您的代码将完美地编译您使用或在参数中调用其构造函数的任何内容。newItemnew Item[..]

如果您想使用指针进行练习,请不要从头停止,要更进一步;-)

于 2019-05-11T13:59:27.660 回答