I have a simple reference counted class that holds a memory buffer. It looks like this:
#include <algorithm>
template<typename T>
struct buffer
{
// create a buffer of length n
buffer(unsigned n) : rc(*(new unsigned(1))), data(new T[n]) { }
buffer(const buffer<T> & rhs) : rc(++rhs.rc), data(rhs.data) { }
buffer<T>& operator=(buffer<T> rhs)
{
std::swap(rc, rhs.rc);
std::swap(data, rhs.data);
return *this;
}
~buffer()
{
if (--rc == 0) {
delete [] data;
delete (&rc);
}
}
private:
mutable unsigned & rc;
T * data;
};
int main() {
typedef buffer<int> numbers;
numbers n1(10);
numbers n2(20);
numbers n3(30);
n1 = n2 = n3 = n2;
}
I don't see anything wrong with the code. However Visual Studio and valgrind complain about memory corruption.
I've stared at this code for way too long now. Can anyone spot the error?
One problem is that when you swap(rc, rhs.rc); you're actually swapping the contents of the recounts, not the references.
Imagine you have this situation:

When you swap(rc, rhs.rc);, the references to the refcounts will remain the same, and the counts themselves will swap. This is what you get after the two swaps:

The buffer pointers are corrrect, but the references to the refcounts still refer to the same unsigned objects. The value of these objects was swapped though. Notice how the buffer B has refcount 2 when seen from one of the swapped objects, and refcount 1 when seen from the one on the bottom.
You need to use pointers for the refcount, and swap the pointers, not the contents.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With