I have a class in my C++ code which has its own move constructor. A simplified version is shown here:
class myClass {
//In this example, myClass must manually manage allocating
//and freeing a memory buffer.
char *mem;
//...
//Regular constructor, copy constructor, etc
//...
myClass(myClass &&other) {
//Swap our memory pointer with other's memory pointer
char *tmp = other.mem;
other.mem = mem;
mem = tmp;
}
//...
//Destructor, other member functions, etc.
//...
}
In normal situations, this works fine. However, recently I needed to make a vector of these objects:
vector<myClass> v;
v.reserve(10); //Make space, but do not construct
v.push_back(myClass()); //Problem!
After getting a segfault and stepping through with gdb, I eventually discovered what should have been obvious: if you try to construct an object from an rvalue reference, this can result in using the move constructor on uninitialized memory.
How are you supposed to write a move constructor when it's possible that you're swapping garbage into the other
class? Is there some way to detect this?
std::string
? – Flourishingmem
, if only tonullptr
? (Also, there is no reason forother.mem = mem
in your copy constructor; better isfree (mem); mem = other.mem; other.mem = nullptr;
) – Moulmeinfree(other.mem)
should work actually (instead of copying). And by the way, my default constructor does givemem
a reasonable default value; in my case, I was usingstd::vector::reserve
, which wasn't default-constructing the memory (I made an edit to the question to show this). – Enchondromachar*
pointers being passed around like candy I immediately suspect that there's some serious memory management (doublefree
or nofree
at all which leaks) issues here or uninitialized pointer data to blame for the problem.std::string
keeps things simple. – Flourishingfree(mem)
is still potentially freeing a garbage pointer. – Enchondromamem
). – Kipparother.mem
might be uninitialized (or what you meant by "uninitialized move", if it isn't). – Shawanda