0

I'm writing a program aiming to simulate coral growth and I want corals to be some kind of binary tree. Branches are the equivalent of nodes. When I run the program I got a "segmentation fault" error and after testing and doing some research I'm thinking it is because the destructor of Coral class is trying to delete a NULL object. However I have no clue on how to solve it since I don't fully understand how a destructor works and I'm not familiar at all with the concept of class.

I give you the header file where CoralBranch and Coral classes are declared, the .cpp where the classes are implemented and the main.cpp.

Thank you all in advance.

Working in a Minimal, Complete, and Verifiable example that reproduces my problem, I run into no problem. I think I have other errors in my program which provoque the segmentation faults at methods which shouldn't have problems.

coral2.h

#ifndef __CORAL2_H_INCLUDED__
#define __CORAL2_H_INCLUDED__

class CoralBranch{

  public:

CoralBranch(); // class constructor 1
CoralBranch(double xpos, double zpos, double th); // class constructor 2
~CoralBranch();

CoralBranch *left; // pointer to left child
CoralBranch *right; // pointer to right child
double x; // x-position of the beggining of the branch
double z; // z-position of the beggining of the branch
double theta; // branch's direction: angle between the branch and z-axis
double length; // branch's length
int state; // state==1: branch is able to grow, state==0: branch can't grow

};


class Coral{

  public:

Coral(); // class constructor 1
Coral(double bl, double gr, double ir, double dt); // class constructor 2
~Coral(); // class destructor

// adds theta-oriented left son to coral-branch *leaf
void add_left(CoralBranch *leaf, double theta);
// adds theta-oriented right son to coral-branch *leaf
void add_right(CoralBranch *leaf, double theta);
// destroys coral-branch *branch and its decendents
void destroy_coral(CoralBranch *branch);
// tests if the growing branch influence zone penetrates testbranch influence zone
void distance_test(Coral crl, CoralBranch *growingbranch, CoralBranch *testbranch);
// tests if the growing branch is big enough to have children and adds them
void branching_test(Coral crl, CoralBranch *growingbranch, double thetaleft, double thetaright);
// applies grow mechanism to growing branch
void branch_grow(Coral crl, CoralBranch *growingbranch);
// simulates the growing process for the entire colony after one time step by
// applying "branch_grow" to the whole colony
void coral_grow(Coral crl, CoralBranch *growingbranch);

  //private:

CoralBranch *trunk;

double branching_length;
double growth_rate;
double influence_radius;
double Deltat;


};

#endif

coral2.cpp (only constructors and destructors)

CoralBranch::CoralBranch():left(NULL),right(NULL),x(0.0),z(0.0),theta(0.0),length(1.0),state(1)
{
 // there isn't any methods in this class
}

CoralBranch::CoralBranch(double xpos, double zpos, double th):left(NULL),right(NULL),x(xpos),z(zpos),theta(th),length(1.0),state(1)
    {

    }

CoralBranch::~CoralBranch(){

  delete left;
  delete right;

}

Coral::Coral(){

  trunk=new CoralBranch();

  branching_length=1.0;
  growth_rate=1.0;
  influence_radius=1.0;
  Deltat=1.0;

}

Coral::Coral(double bl, double gr, double ir, double dt){

 trunk=new CoralBranch();
    //trunk=NULL;

  branching_length=bl;
  growth_rate=gr;
  influence_radius=ir;
  Deltat=dt;

}

Coral::~Coral(){ // coral destruction

  destroy_coral(trunk);

}

void Coral::destroy_coral(CoralBranch *branch){ // destroys branch *branch and its decendents

  if(branch == NULL) return;

  destroy_coral(branch->left);
  destroy_coral(branch->right);
  delete branch;

  /*if(branch!=NULL){

    destroy_coral(branch->left); // destruction advance
    destroy_coral(branch->right);
    delete branch; // currently considered branch is deleted if it exists

  }*/
}

main.cpp

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "coral2.h"
#include <math.h>
using namespace std;

int main(){

  /* Variable declaration, these variables need to be initialized in order to
  construct the coral with the characteristics we desire */
  double branchinglength, growthrate, influenceradius, deltat;
  /* Declaration and initialization of the total simulation time */
  double TotalTime=2;
  /* Declaration and initialization of counters */
  int i=0;
  int j=0;
  printf("%d\n",j);

  /* Initialization of Coral class parameters*/
  branchinglength=0.2;
  growthrate=1.0;
  influenceradius=0.1;
  deltat=1.0;

  /* Creation of the coral object*/
  static Coral GrowingCoral(branchinglength, growthrate, influenceradius, deltat);

  /* Starting growth process */
  for(i=0; i<TotalTime; i=i+deltat){

    j++;
    printf("%d\n",j);

    GrowingCoral.coral_grow(GrowingCoral, GrowingCoral.trunk);

  }

  printf("%f\n",GrowingCoral.branching_length);

  return 0;
}
bengo
  • 325
  • 3
  • 13
  • 2
    Welcome to Stack Overflow. Please take the time to read [The Tour](http://stackoverflow.com/tour) and refer to the material from the [Help Center](http://stackoverflow.com/help/asking) what and how you can ask here. – πάντα ῥεῖ Feb 16 '17 at 17:19
  • 3
    The right tool to solve such problems is your debugger. You should step through your code line-by-line *before* asking on Stack Overflow. For more help, please read [How to debug small programs (by Eric Lippert)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). At a minimum, you should \[edit] your question to include a [Minimal, Complete, and Verifiable](http://stackoverflow.com/help/mcve) example that reproduces your problem, along with the observations you made in the debugger. – πάντα ῥεῖ Feb 16 '17 at 17:19
  • 4
    _"because the destructor of Coral class is trying to delete a NULL object."_ using `delete` with `NULL` or `nullptr` is perfectly fine. Though calling `delete` doesn't set the pointer value to `NULL` or `nullptr.` – πάντα ῥεῖ Feb 16 '17 at 17:22
  • @A.S.H Flabbergasted ;-) – πάντα ῥεῖ Feb 16 '17 at 17:30
  • Why are you copying Coral? you should be aware of the "rule of three" http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three – Lorence Hernandez Feb 16 '17 at 17:36
  • 1
    I removed the first paragraph, because your background should not affect in which way answers are given. Answers should always be such that anybody visiting this site can make sense of it – 463035818_is_not_an_ai Feb 16 '17 at 17:36
  • I used the debugger and it marked an error with destroy_coral method. I did a lot of research before askiing this question. I will read the doc about the rule fo three and post a minimal example. thank you for your help – bengo Feb 16 '17 at 20:03

1 Answers1

1

You are deleting the left and right branches twice.

Think how your CoralBranch works: It owns a left branch and a right branch. Since it owns the branches, it can and should delete them in the destructor ~CoralBranch. And it does! Good.

Your class Coral owns only one object, the trunk. But look what Coral::destroy_coral does! It is allowed to delete branch objects that class Coral does not own! The only CoralBranch it should destroy is the one that it owns, trunk. That one will delete its own child branches via the destructor, and those their own, recursively. Hence, all you have to do is remove the recursive destroy_coral invocations from destroy_coral.

j6t
  • 9,150
  • 1
  • 15
  • 35
  • Thanks for the explanation. I did what you say and I have no more problems with `Coral::destroy_coral`. However I now run into an error in the `CoralBranch::~CoralBranch()` destructor. Working in a minimal example to edit my initial post, I found no problem with running the program. I think my code has other problems... – bengo Feb 17 '17 at 09:59