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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.