can’t figure out where the heap overwriting is

#include<iostream>

using namespace std;

class Text{
public:
~Text(){
    delete data;
}
    char* data{};
    int mSize{};
    void fill(char* stringInput) {
        mSize = strlen(stringInput);
        data = new char [mSize];
        for (int i = 0; i < mSize; i++){
            data[i] = stringInput[i];
        }
    }

};

class myString{
public:
    explicit myString(int size){ // constructor
        strAmount = size;
        strings = new Text [size];
    }

    ~myString(){ // destructor
        delete[] strings;
    }
    void addString(char* input){
        strings[filledAmount].fill(input);
        filledAmount++;
    }
    void delString(int pos){
        for ( int i = pos; i < filledAmount; i++){
            swap(strings[i], strings[i+1]);
        }
        strings[filledAmount].data = nullptr;
        strings[filledAmount].mSize = 0;
        filledAmount--;
    }
    void eraseEverything(){
        for ( int i = 0; i < filledAmount; i++){
            strings[i].data = {};
            strings[i].mSize = 0;
        }
        filledAmount = 0;
    }
    int maxString() const {
        int index{};
        for ( int i = 0 ; i < filledAmount; i++){
            if (strings[i].mSize > strings[index].mSize){
                index = i;
            }
        }
        return index;
    }
    int charAmount(){
        int counter{};
        for(int i = 0 ; i < filledAmount; i++){
            counter+=strings[i].mSize;
        }
        return counter;
    }
    double digitPercentage(){
        int digitsAmount{};
        for(int i = 0; i < filledAmount; i++){
            for ( int j = 0; j < strings[i].mSize; j++){
                if (isdigit(strings[i].data[j])){
                    digitsAmount++;
                }
            }
        }
        double digitPercent = (digitsAmount/(double)charAmount())*100;
        return digitPercent;
    }

    int filledAmount{};

    int strAmount{};
    Text* strings;

};

void render_text(myString& obj) {
    for (int k = 0; k < obj.filledAmount; k++) {
        for (int i = 0; i < obj.strings[k].mSize; i++)
            cout << obj.strings[k].data[i];
        cout << endl;
    }
    cout << endl;
    }

int main(){
    myString a(5);

    a.addString((char *) "zxc 1v1 forever shadow fiend");
    a.addString((char *) "This is a string");
    a.addString((char *) "12345");
    a.addString((char *) "Hello");
    a.addString((char *) "A1oha Dance");
    render_text(a);

    a.delString(1);
    render_text(a);

    int maxInd = a.maxString();
    cout << "Max string :n";
    for (int i = 0; i < a.strings[maxInd].mSize; i++) {
        cout << a.strings[maxInd].data[i];
    }
    cout << "nn";
    }

Please help me find the crash point. I suppose it crashes in the destructor pole, but I still can’t figure it out.

This is something like a self-written string class, the problem is that I can’t find the place where the problems start.

I also have a thought that the destructor tries to delete too much memory from the heap so the compiler prevents it from doing that. Can I somehow change the size of the strings array?

Answer

I have fixed all your memory errors, with the help of address sanitizers

The main change here is:

  • Add copy constructors and copy assignment operators
  • Manually delete the last element in the function delString

Though that the code now works, it’s not a true modern c++ style code. I highly recommend that your using std::string to replace your Text class. Use std::vector to replace the dynamic array. Then you will stay away from the pain of memory errors. The delString should be replaced with vector::erase,which is much neat than your hand write algorithm.

https://en.cppreference.com/w/cpp/string/basic_string https://en.cppreference.com/w/cpp/container/vector

I strongly recommend rewriting the code with std::string and std::vector

#include <cstring>
#include <iostream>

using namespace std;

class Text {
 public:
  ~Text() { delete[] data; }
  char* data{};
  int mSize{};
  Text() = default;
  Text(const Text& oth) {
    mSize = oth.mSize;
    data = new char[mSize];
    std::copy(oth.data, oth.data + oth.mSize, data);
  }
  Text& operator=(const Text& oth) {
    delete[] data;
    mSize = oth.mSize;
    data = new char[mSize];
    std::copy(oth.data, oth.data + oth.mSize, data);
    return *this;
  }

  void fill(char* stringInput) {
    mSize = strlen(stringInput) + 1;
    data = new char[mSize];
    for (int i = 0; i < mSize; i++) {
      data[i] = stringInput[i];
    }
  }
};

class myString {
 public:
  explicit myString(int size) {  // constructor
    strAmount = size;
    strings = new Text[size];
  }

  myString(const myString& oth) {
    strAmount = oth.strAmount;
    strings = new Text[oth.strAmount];
    for (size_t i = 0; i < strAmount; ++i) {
      strings[i] = oth.strings[i];
    }
  }
  myString& operator=(const myString& oth) {
    delete[] strings;

    strAmount = oth.strAmount;
    strings = new Text[oth.strAmount];
    for (size_t i = 0; i < strAmount; ++i) {
      strings[i] = oth.strings[i];
    }
    return *this;
  }

  ~myString() {  // destructor
    delete[] strings;
  }
  void addString(char* input) {
    strings[filledAmount].fill(input);
    filledAmount++;
  }
  void delString(int pos) {
    for (int i = pos; i < filledAmount; i++) {
      swap(strings[i], strings[i + 1]);
    }
    delete[] strings[filledAmount].data;
    strings[filledAmount].data = nullptr;
    strings[filledAmount].mSize = 0;
    filledAmount--;
  }
  void eraseEverything() {
    for (int i = 0; i < filledAmount; i++) {
      strings[i].data = {};
      strings[i].mSize = 0;
    }
    filledAmount = 0;
  }
  int maxString() const {
    int index{};
    for (int i = 0; i < filledAmount; i++) {
      if (strings[i].mSize > strings[index].mSize) {
        index = i;
      }
    }
    return index;
  }
  int charAmount() {
    int counter{};
    for (int i = 0; i < filledAmount; i++) {
      counter += strings[i].mSize;
    }
    return counter;
  }
  double digitPercentage() {
    int digitsAmount{};
    for (int i = 0; i < filledAmount; i++) {
      for (int j = 0; j < strings[i].mSize; j++) {
        if (isdigit(strings[i].data[j])) {
          digitsAmount++;
        }
      }
    }
    double digitPercent = (digitsAmount / (double)charAmount()) * 100;
    return digitPercent;
  }

  int filledAmount{};

  int strAmount{};
  Text* strings = nullptr;
};

void render_text(myString& obj) {
  for (int k = 0; k < obj.filledAmount; k++) {
    for (int i = 0; i < obj.strings[k].mSize; i++)
      cout << obj.strings[k].data[i];
    cout << endl;
  }
  cout << endl;
}

int main() {
  myString a(6);

  a.addString((char*)"zxc 1v1 forever shadow fiend");
  a.addString((char*)"This is a string");
  a.addString((char*)"12345");
  a.addString((char*)"Hello");
  a.addString((char*)"A1oha Dance");
  render_text(a);

  a.delString(1);
  render_text(a);

  int maxInd = a.maxString();
  cout << "Max string :n";
  for (int i = 0; i < a.strings[maxInd].mSize; i++) {
    cout << a.strings[maxInd].data[i];
  }
  cout << "nn";
  return 0;
}