3

I have a class, Agent, with a member attribute pointer to an object of another class, Form:

Agent.h

...//snip includes
class Agent{
private:
  Form* mvForm_ptr;
  ...
public:
  Agent();
  ~Agent();
  ...//snip additional functionality, but no copy-constructor
};

Agent.cpp

#include "Agent.h"
Agent::Agent(){
  mvForm_ptr = new Form();
}
Agent::~Agent(){
  delete mvForm_ptr;
}
...

As you can see, I do not have an explicit copy-constructor for Agent. Later, I use Agent as follows:

Agent player;
std::vector<Agent> agentsVector;
agentsVector.push_back(player);

This seems to be the cause of a SIGSEGV crash whose error report claims that ~Agent is throwing an EXC_BAD_ACCESS exception. Reading up on vector::push_back here it seems that push_back attempts to copy the passed in value. Since I don't have a copy-constructor in class Agent, what happens to the Form pointer upon an implicit copy attempt? If the pointed-to value is lost in the compiler-generated implicit copy-constructor, would adding an explicit copy-constructor resolve the bad access exception? How should a copy-constructor for class Agent above be implemented? Is this an example of the premise described by the Rule of Three?

CCJ
  • 1,619
  • 26
  • 41

2 Answers2

2

what happens to the Form pointer upon an implicit copy attempt?

What happens is that the pointer data member is copied, which means both the original and the copy point to the same object, which in turn means that both of them will attempt to delete it when their life comes to an end. Only one of these deletes can succeed. The other leads to undefined behaviour.

In C++11, you can fix this problem by holding an std::unique_ptr<Form> instead of a raw pointer. In C++03, follow the rule of three.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

Since you did not supply a copy or assignment operator the compiler will generate one for you and the pointer will be copied but not the Form. On every destruction of the Agent your pointer will be freed and you will free the same memory multiple times.

A simple fix would be to use shared_ptr to make sure the Form is only deleted when there are no more agents.

Sarien
  • 6,647
  • 6
  • 35
  • 55
  • Remark: That "simple fix" will make all copied `Agent`s use the same `Form`, which will most-likely result in unwanted behaviour (except if the OP actually wants this). – Zeta Mar 11 '13 at 21:48
  • I think unique_ptr are the better alternative, right? Then again with the copies made by vector operations the result would likely be the same. But you are still correct and my approach is wrong here. He should probably prevent copying and implement move semantics. – Sarien Mar 11 '13 at 21:51