无法弄清楚堆覆盖在哪里

时间:2021-03-31 12:05:56

标签: c++ class destructor heap-memory

#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 << "\n\n";
    }

请帮我找到崩溃点。我想它在析构极点崩溃了,但我仍然无法弄清楚。

这有点像自己写的字符串类,问题是我找不到问题开始的地方。

我也有一个想法,析构函数试图从堆中删除太多内存,因此编译器阻止它这样做。我可以以某种方式更改 strings 数组的大小吗?

1 个答案:

答案 0 :(得分:0)

在地址 sanitizers

的帮助下,我已修复了您的所有内存错误

这里的主要变化是:

  • 添加复制构造函数和复制赋值运算符
  • 手动删除函数delString中的最后一个元素

尽管代码现在可以工作,但它并不是真正的现代 C++ 风格代码。我强烈建议您使用 std::string 替换 Text 类。使用 std::vector 替换动态数组。那么你将远离记忆错误的痛苦。 delString 应该替换为 vector::erase,这比您的手写算法要简洁得多。

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

我强烈建议使用 std::stringstd::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 << "\n\n";
  return 0;
}