0

I am trying to write a basic string class for practice, and I am struggling with the reserve() function to increase my char array's memory allocation.

This is the error message I get:

free(): double free detected in tcache 2

This is my approach:

void string::reserve(size_t n)
{
    if (n <= space+1) return; // never decrease allocation
    char *p = new char[n+1]; // allocate new space
    for (int i=0; i<sz; ++i) p[i]=pChars[i]; // copy old elements
    //strcpy(p, pChars); // didn't work either
    p[n] = '\0';
    delete[] pChars; // deallocate old space
    pChars = p;
    space = n+1;
}

I will also share a picture of my header file below:

image

Here is the entire code:

#include "String.h"
namespace String
{
    string::string(): sz(0), pChars(nullptr), space(0) {}
    string::string(const char* s): sz(strlen(s)), pChars(new char[strlen(s)+1]), space(sz+1)          ///Constructor using a null-terminated C String
    {
        //for (int i = 0; s[i] != '\0'; i++) pChars[i] = s[i];
        strcpy(pChars,s);
        pChars[strlen(s)] = '\0';
    }
    string::string(const string& s): sz(s.sz), pChars(new char[s.sz]), space(s.sz)        ///copy constructor
    {
        for (size_t i = 0 ; i<s.sz; i++) pChars[i] = s.pChars[i];
        pChars[s.sz] = '\0';
    }
    string& string::operator=(const string& s)     ///copy assignment
    {
        if (this==&s) return *this; // self-assignment, no work needed
        if (s.sz<=space) 
            { // enough space, no need for new allocation
                for (size_t i = 0; i<s.sz; ++i) pChars[i] = s.pChars[i]; // copy elements
                sz = s.sz;
                return *this;
            }
        char *p = new char [s.sz]; // copy and swap
        for (size_t i = 0; i<s.sz; ++i) p[i] = s.pChars[i];
        delete[] pChars;
        sz = s.sz;
        space = s.sz;
        pChars = p;
        return *this; 
    } 
    string& string:: operator=(const char* s)       ///copy assignment using a null-terminated C String
    {
        char *p = new char[strlen(s)+1];
        for(size_t i = 0; s[i] != '\0'; i++) p[i] = s[i];
        p[sz] = '\0';
        delete [] pChars;
        sz = strlen(s);
        space = sz;
        strcpy(pChars, p);
        return *this;     

    }
    ///string(string&& s);                  ///move constructor, not needed (compiler copy elision)
    string& string:: operator=(string&& s)         ///move assignment
    {
        delete[] pChars; // deallocate old space
        pChars = s.pChars;  // copy a's elem and sz
        sz = s.sz;
        space = s.space;
        s.pChars = nullptr; // make a the empty vector
        s.sz = 0;
        cout << "Move" << endl;
        return *this;        
    }
    string::~string()
    {
        delete [] pChars;
    }
    char& string:: operator[](size_t pos) {return pChars[pos];}            ///set operator
    const char& string:: operator[](size_t pos) const {return pChars[pos];}   ///get operator

    void string::reserve(size_t n)
    {
        if (n <= space+1) return; // never decrease allocation
        char *p = new char[n+1]; // allocate new space
        for (int i=0; i<sz; ++i) p[i]=pChars[i]; // copy old elements
        //strcpy(p, pChars);
        p[sz] = '\0';
        delete[] pChars; // deallocate old space
        pChars = p;
        space = n+1;
    }
    void string:: push_back(const char c)                   ///push char c to the end
    {
        if (sz==0)  // no space: grab some
        reserve(8);
        else if (sz==space)  // no more free space: get more space
        reserve(2*space);
        pChars[sz] = c; // add d at end
        ++sz; // and increase the size (sz is the number of elements)

    }



    bool operator==(const string& lhs, const string& rhs)  ///check equality (same size, all chars the same)
    {
        if (lhs.size() != rhs.size()) return false;
        else
        {
            for (size_t i = 0; i<lhs.size(); i++)
            {
                if (lhs[i] != rhs[i]) return false;
            }
            
        }
        return true;
    }
    bool operator==(const string& lhs, const char* rhs)    ///equality with null terminated C string
    {
        if(lhs.size() == strlen(rhs))
        {
            for (size_t i = 0; i< lhs.size(); i++)
            {
                if(lhs[i] == rhs[i]) return true;
            }
        }
        return false;
    }

    bool operator>(const string& lhs, const string& rhs)   ///greater than operator, true if lhs > rhs
    {

    }
    string operator+(const string& lhs, const string& rhs) ///concatenate two MyStrings, return the result
    {

    }
    ostream& operator<<(ostream& os, const string& s)
    {

        for (size_t i = 0; i<s.size(); i++)
            {
                os << s[i];
            }
        return os;
    }
    istream& operator>>(istream& is, string& s)
    {
        char c;
        while(is.get(c))
        {
            if (c!=' ') s.push_back(c);
        }
        return is;
        
    }

}
7
  • 1
    Why p[n] = '\0'; instead of p[sz] = '\0';? This might be a reason why strcpy did not work. Commented Apr 22, 2022 at 23:38
  • use a naming convention for your data members Commented Apr 22, 2022 at 23:39
  • 1
    I suggest using std::vector in the custom string class. Commented Apr 22, 2022 at 23:41
  • you seem to have trashed your heap elsewhere, we gonna need to see the rest of the code Commented Apr 22, 2022 at 23:42
  • 1
    it would be nice to have the header and a test main - debugging by just reading code is tedious. One serious error found so far Commented Apr 23, 2022 at 0:06

1 Answer 1

2

First error

string::string(const string& s): sz(s.sz), pChars(new char[s.sz]), space(s.sz)        ///copy constructor
{
    for (size_t i = 0 ; i<s.sz; i++) pChars[i] = s.pChars[i];
    pChars[s.sz] = '\0';
}

This allocates an array of s.sz chars and then writes off the end of it

SHould be

string::string(const string& s): sz(s.sz), pChars(new char[s.sz] + 1), space(s.sz)        ///copy constructor
{
    for (size_t i = 0 ; i<s.sz; i++) pChars[i] = s.pChars[i];
    pChars[s.sz] = '\0';
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.