std::swap Corruption [Answered]
-
I am using Visual Studio 2010 Pro, and have a unique issue that I'm hoping someone can help with. I overloaded the move operator = on a class, with the following code:
template<class T>
MyClass<T> &MyClass<T>::operator =(MyClass &&other) {
if (this != &other) {
std::swap(m_Data , other.m_Data ); // T*
std::swap(m_Size1, other.m_Size1); // size_t
std::swap(m_Size2, other.m_Size2); // size_t
std::swap(m_Size3, other.m_Size3); // size_t
std::swap(m_Bool1, other.m_Bool1); // bool
std::swap(m_Bool2, other.m_Bool2); // bool
}
return *this;
}When I enter this method in the debugger, all of the fields of both *this and other are what I expect. In case it matters, the values are:
\*this other
m_Data 0 0x15E4D2EC0
m_Size1 0 5041
m_Size2 0 5041
m_Size3 0 1
m_Bool1 true false
m_Bool2 true trueMy expectation is that the calls to std::swap exchange the values of all the aforementioned fields. However, on the first call to swap, when I step into the function, I get that _Left = 0 and _Right = 0x7FEF5B07EDF. WTF? Why did the value of _Right change from 0x15E4D2EC0? Even more confusing, is that at the end of the function, _Left = 0x7FEF5B07EDF, _Right = 0, but upon returning, the value of other.m_Data has NOT changed to 0. Additionally, the following fields in the "other" object changed to the values indicated (after only executing the first std::swap):
other
m_Data 0x7FEF5B07EDF (should be 0)
m_Size1 67251472 (should be 5041)
m_Size2 0 (should be 5041)
m_Size3 67257296 (should be 1)
m_Bool1 true (should be false)
m_Bool2 true (should be true)WTF? Why does calling std::swap on a single field totally hose my entire object? It is as if the first call somehow changed the type of other. Can anyone shed some light onto what is happening here? Additionally, when the future calls of std::swap are executed (all but the first), they copy the value from other to *this, but don't change the value of other (for example, after executing std::swap(m_Size1, other.m_Size1), I would expect m_Size1 = 67251472 (which it does), and other.m_Size1 = 0 (it is still equal to 67251472). Thanks,
Sounds like somebody's got a case of the Mondays -Jeff
-
I am using Visual Studio 2010 Pro, and have a unique issue that I'm hoping someone can help with. I overloaded the move operator = on a class, with the following code:
template<class T>
MyClass<T> &MyClass<T>::operator =(MyClass &&other) {
if (this != &other) {
std::swap(m_Data , other.m_Data ); // T*
std::swap(m_Size1, other.m_Size1); // size_t
std::swap(m_Size2, other.m_Size2); // size_t
std::swap(m_Size3, other.m_Size3); // size_t
std::swap(m_Bool1, other.m_Bool1); // bool
std::swap(m_Bool2, other.m_Bool2); // bool
}
return *this;
}When I enter this method in the debugger, all of the fields of both *this and other are what I expect. In case it matters, the values are:
\*this other
m_Data 0 0x15E4D2EC0
m_Size1 0 5041
m_Size2 0 5041
m_Size3 0 1
m_Bool1 true false
m_Bool2 true trueMy expectation is that the calls to std::swap exchange the values of all the aforementioned fields. However, on the first call to swap, when I step into the function, I get that _Left = 0 and _Right = 0x7FEF5B07EDF. WTF? Why did the value of _Right change from 0x15E4D2EC0? Even more confusing, is that at the end of the function, _Left = 0x7FEF5B07EDF, _Right = 0, but upon returning, the value of other.m_Data has NOT changed to 0. Additionally, the following fields in the "other" object changed to the values indicated (after only executing the first std::swap):
other
m_Data 0x7FEF5B07EDF (should be 0)
m_Size1 67251472 (should be 5041)
m_Size2 0 (should be 5041)
m_Size3 67257296 (should be 1)
m_Bool1 true (should be false)
m_Bool2 true (should be true)WTF? Why does calling std::swap on a single field totally hose my entire object? It is as if the first call somehow changed the type of other. Can anyone shed some light onto what is happening here? Additionally, when the future calls of std::swap are executed (all but the first), they copy the value from other to *this, but don't change the value of other (for example, after executing std::swap(m_Size1, other.m_Size1), I would expect m_Size1 = 67251472 (which it does), and other.m_Size1 = 0 (it is still equal to 67251472). Thanks,
Sounds like somebody's got a case of the Mondays -Jeff
Nevermind: I'm an idiot. I didn't realize that rvalue references are returned automatically, and had a function declared similar to the following:
MyClass<double> &&Foo() {
MyClass<double> result();
return std::move(result);
}I simply had to remove the double ampersand from the return type, and my move constructor/assignment operator were correctly called. The reason that I saw this weird behavior was because the object that I had a reference to was allocated on the stack. Once enough functions were called (overwriting any pre-existing, invalid stuff on the stack), the object I was using was overwritten. Thanks for anyone who looked into this!
Sounds like somebody's got a case of the Mondays -Jeff