Search code examples
c++freedelete-operatorexit-codedouble-free

free(): double free detected in tcache 2 on calling overloaded assignment operator


I'm working on a university project where we are to implement some of the c++ string class as Mystring. I'm working on the overloaded assignment operator and this is the current code for it:

Mystring& Mystring::operator=(const Mystring& orig)
{
    if(this != &orig)
    {
        delete ptr_buffer;
        len = orig.len;
        buf_size = orig.buf_size;
        ptr_buffer = orig.ptr_buffer;
    }
    return *this;

}

ptr_buffer, len. and buf_size are the three private variables for the Mystring class. This is my main program to test:

void check (const Mystring s, const string name)
{
    cout << "checking " << name << endl;
    cout << name << " contains " << s << endl;
    cout << name << " capacity() is " << s.capacity() << endl;
    cout << name << " length() is " << s.length() << endl;
    cout << name << " size() is " << s.size() << endl;
    cout << name << " max_size() is " << s.max_size() << endl << endl;
}


int main()
{
    Mystring s1("Hi there!");
    check(s1, "s1");

    Mystring s2("Testing before assignment!");
    check(s2, "s2");
    s2 = s1;
    check(s2, "s2");
    return 0;
}

This is what that outputs:

checking s1
s1 contains Hi there!
s1 capacity() is 10
s1 length() is 9
s1 size() is 9
s1 max_size() is 1073741820

checking s2
s2 contains Testing before assignment!
s2 capacity() is 27
s2 length() is 26
s2 size() is 26
s2 max_size() is 1073741820

checking s2
s2 contains Hi there!
s2 capacity() is 10
s2 length() is 9
s2 size() is 9
s2 max_size() is 1073741820

free(): double free detected in tcache 2

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

As you can see, the assignment DOES work to set all the member variables, however I get a non-zero exit code and a free(): double free detected in tcache 2 error. What am I doing wrong and what does this error mean? I've confirmed that the exit code is coming from calling the assignment, because when I comment out s2 = s1;, it completes with exit code 0.


Solution

  • In this copy assignment operator

    Mystring& Mystring::operator=(const Mystring& orig)
    {
        if(this != &orig)
        {
            delete ptr_buffer;
            len = orig.len;
            buf_size = orig.buf_size;
            ptr_buffer = orig.ptr_buffer;
        }
        return *this;
    }
    

    there are at least two problems. If the array of characters pointed to by the pointer ptr_buffer was allocated dynamically then you have to use the operator delete [] instead of delete

    delete [] ptr_buffer;
    

    The second problem is that after this assignment

    ptr_buffer = orig.ptr_buffer;
    

    two pointers point to the same dynamically allocated memory.

    You need to allocate a new extent memory and copy there the string of the assigned object.

    The operator can be defined at least the following way

    Mystring & Mystring::operator =( const Mystring &orig )
    {
        if(this != &orig)
        {
            if ( buf_size != orig.buf_size )
            {
                delete [] ptr_buffer;
                ptr_buffer = new char[orig.buf_size];
                buf_size = orig.buf_size;
            } 
            len = orig.len;
            strcpy( ptr_buffer, orig.ptr_buffer );
            // or if the class does not store strings then
            // memcpy( ptr_buffer, orig.ptr_buffer, len ); 
        }
    
        return *this;
    }