samedi 4 novembre 2017

Empty cout prevents segmentation fault caused by delete

I'm trying to learn about object-oriented programming in C++, and I run in a "Segmentation fault" error caused by a delete operation. In my main function, I have the subsequent code:

while (Event* ev = read(datafile)) {
  k0.add(*ev);
  lambda0.add(*ev);
  //cout << "";
  delete ev;
}

If I uncomment the cout the error is prevented, and the program outputs the correct result.

Here is the read function:

Event* read(ifstream &file) {
int event_id;

if (! (file >> event_id) ) { //Check if file contains data
  return 0;
} else {
  int num_particles;
  float pos[3];
  for (int i = 0; i < 3; ++i) { //Load particle position
    file >> pos[i];
  }
  file >> num_particles; //Load number of particles

  Event *event = new Event(event_id, pos[0], pos[1], pos[2]); //Create class instance

  for (int i = 0; i < num_particles; ++i) { //For each particle: load particle data
    float momentum[3];
    int charge;
    file >> charge;
    for (int j = 0; j < 3; ++j) {
      file >> momentum[j];
    }
    event->add(momentum[0], momentum[1], momentum[2], charge); //and add it to the class

  }
  return event; //then return pointer to the new object
}
}

And here is the Event class:

Event.h

#ifndef Event_h
#define Event_h

class Event {

 public:

 Event( int n, float x, float y, float z ); //Constructor: event identifier + position coordinates (x, y, z)
  ~Event(); //Destructor

  // composite object Particle to hold all information for each particle
  // ( x,y,z momentum components and electric charge )
  struct Particle {
    int charge;
    float momentum[3];
  };
  typedef const Particle* part_ptr; //Pointer to Particle struct

  // add a particle to the event
  void add( float px, float py, float pz, int charge );

  // get event id.
  int eventNumber() const;
  // get decay point coordinates
  float x() const;
  float y() const;
  float z() const;
  // get number of particles
  int nParticles() const;
  // get particle
  const Particle* particle( unsigned int i ) const;

 private:
  static const int MAX_PARTICLES = 10;

  // event-specific informations:
  int event_identifier; // event id
  float pos[3]; // decay point

  // particles: number and array of pointers
  int particle_number;
  part_ptr *particles; //array of particles

};

#endif

And Event.cc

#include "Event.h"
#include <iostream>

Event::Event( int n, float x, float y, float z ): //Constructor
 event_identifier(n), //Initialize variables
 particle_number(0)
{
  pos[0] = x;
  pos[1] = y;
  pos[2] = z;
  particles = new part_ptr[MAX_PARTICLES]; //Allocate particle array
}


Event::~Event() {
  for (int i; i < particle_number; ++i) { //Free memory
    delete particles[i];
  }
  delete[] particles;
}


void Event::add( float px, float py, float pz, int charge ) {
  if (particle_number == MAX_PARTICLES) { //If MAX_PARTICLES reached, do nothing
    return;
  }

  particles[particle_number] = new Particle({charge, px, py, pz}); //Allocate new Particle

  particle_number++; //Increase counter

  return;

}


// get event id.
int Event::eventNumber() const {
  return event_identifier;
}

//Get coordinates
float Event::x() const {
  return pos[0];
}

float Event::y() const {
  return pos[1];
}

float Event::z() const {
  return pos[2];
}

//Get number of particles
int Event::nParticles() const {
  return particle_number;
}

// get specific particle
const Event::Particle* Event::particle( unsigned int i ) const {
  if (i < particle_number) { //Check if particle exists
    return particles[i];
  } else {
    return 0;
  }
}

If you want to try the code, I've uploaded it to Github here.

Aucun commentaire:

Enregistrer un commentaire