指针被分配的测试类析构函数?

时间:2015-06-01 02:59:02

标签: c++ pointers c++11

所以我的代码出了问题。我想将指针数组中的值传递给函数,这样原始对象就不会受到干扰。 (如果我通过参考,我的代码工作得非常好;我只是尝试以不同的方式进行学习练习)。实现返回后,我收到一个错误:

"对象0x100105790的错误:未分配被释放的指针 ***在malloc_error_break中设置一个断点来调试"。

我知道这是因为当函数返回时值超出范围,对象调用析构函数但我的析构函数假定已分配的指针,因此错误。我很好奇是否有办法测试基因组是否已经分配。如果不是我会为析构函数做其他事情?这是否是一个值得烦恼的问题,因为我已经通过传递参考工作了?该功能实际上并不具有破坏性;我只是想做一些技巧。我不喜欢走简单的路。

//class destructor for int genome[]
Organism::~Organism() {
    //cout << "Deleting this: " << this << endl;
    if (this->genome != NULL) {
         delete [] this->genome;
    }
}

//declare genome pointer
int *genome;
/**
 * Default constructor for class
 */
Organism::Organism() {
    this->fitness = 0;
    this->size = 0;
    this->genome = NULL;
}
//another constructor for if only the size of genome is defined
Organism::Organism(int size) {
    this->fitness = 0;
    this->size = size;
    this->genome = new int[size];
}
//another constructor for when all starting values are defined
Organism::Organism(int size, int *genome) {
    this->fitness = 0;
    this->size = size;
    this->genome = new int[size];

    for (int i = 0; i < size; i++) {
        this->genome[i] = genome[i];
    }
 }

//initialize and populate reproducible from already existing array start_pop     (this has been verified as being properly allocated and values initiated)
vector<Organism*> reproduceable (0);
    for (int i = 0; i < start_pop.size(); i++) {
        if (start_pop[i]->get_fitness() > threshold) {
            reproduceable.push_back(start_pop[i]);
        }
    }

//function definition
Organism* reproduce(Organism, Organism);

//function call in main()
offspring.push_back(reproduce(*reproduceable[i], *reproduceable[i+1]));

//function implementation
Organism* reproduce(Organism a, Organism b) {
    int genome[4];

    //randomly decide on where to split parent genomes
    int split = rand() % 5;
    for (int i = 0; i < a.get_size(); i++) {
        if (i < split) {
            genome[i] = a.get_genome()[i];
        } else {
            genome[i] = b.get_genome()[i];
        }
    }
    //now cause random mutation in 2% of the population
    if ((rand() % 100 + 1) <= 2) {
        int rand_index = rand() % 5;
        int mutation = rand() % 6 + 1;

        genome[rand_index] = mutation;
    }

    Organism *child = new Organism(4, genome); //need to add genome
    return child;
}

编辑为可重现的

添加默认构造函数和数组初始化

2 个答案:

答案 0 :(得分:1)

你的问题在这一行:

offspring.push_back(reproduce(*reproduceable[i], *reproduceable[i+1]));

请注意,您将两个reproduceable按值传递给函数。函数的签名是

Organism* reproduce(Organism a, Organism b)

它期望两个Organism的值,这意味着对于Organism两个都将调用复制构造函数。由于您没有定义复制构造函数,因此将创建一个默认的复制构造函数,只将一个生物体的内容复制到另一个生物体中,包括指向基因组的指针。问题是现在两个Organism都将被释放 - 这个函数是本地的,并且是传递给它的那个,导致双重释放为基因组分配的内存。有两种方法可以解决它:

  1. 使签名
  2. Organism* reproduce(const Organism &a, const Organism &b)
    

    这样您的Organism将不会被复制,因此不会被双重释放。 (基于你的问题,我假设你已经尝试过了,并对第二种解决方案感兴趣:))

    1. 实现自定义复制构造函数,创建一个新数组,如此
    2. Organism::Organism(const Organism& a)
      {
           this->fitness = a.fitness;
           this->size = a.size;
           this->genome = new int[this->size];
           for (int i = 0; i < this->size; ++ i)
               this->genome[i] = a.genome[i];
      }
      

      通过这种方式,当您将有机体传递到您的函数中时,将调用您的自定义复制构造函数,并且将单独分配函数本地有机体的genome

答案 1 :(得分:1)

三条规则

如果一个类需要用户定义的析构函数,那么用户定义的副本
它几乎是构造函数或用户定义的复制赋值运算符 当然需要这三个。

请参阅http://en.cppreference.com/w/cpp/language/rule_of_three

虽然更好的方法是规则为零,但是你接受了价值语义。
对于这个程序,它就像更改genome成员一样简单 从int*int[4]std::array<int,4>std::vector<int>
(并删除析构函数)