I have this:
enum Units { Pounds, Kilos };
struct Configuration
{
const Units units;
const char *name;
inline Configuration(Units pUnits, char *pName) : units(pUnits)
{
name = strdup(pName);
}
inline ~Configuration() { free((void *)name); }
};
I was passing one of these to a method like this:
Configuration cc(Kilos, "abc");
cdao->write(cc);
I was getting nasty crashes from this until I tried redefining the method to take a reference:
Configuration cc(Kilos, "abc");
cdao->write(&cc);
And now everything works.
But how could the struct by value be screwing with memory?
You didn’t provide your own copy constructor or assignment operator. So, when you make a copy or an assignment, the compiler-generated copy constructors and assignment operators are used which actually don’t do the right thing in this case. They simply copy every member so you end up with two Configuration objects referring to the same character array. And both Configuration objects feel responsible for deleting the array which almost certainly leads to a “double-deletion” error.
Keep in mind the “rule of three“. The problem here is that the pointer doesn’t behave like you want it to. If you had used a std::string as member you wouldn’t have to write your own copy constructor, destructor, assignment operator. That’s because the compiler-generated ones simply invoke the relevant operations on their members and the string-member already handles this correctly — unlike a pointer to char.