我想实现2个数组加法,但是当析构函数被添加到类SList时
void operator+(SList list2) {
        int totalLen = this->len + list2.len;
        char** temp = new char* [totalLen];
        for(int i = 0; i < len; i++) {
            temp[i] = this->list[i];
        }
        for(int i = len, j = 0; i < totalLen; i++, j++) {
            temp[i] = list2.get(j);
        }
        delete[] this->list;
        this->list = temp;
        this->len = totalLen;
        cout << len << endl << endl;
    }下面是get方法,它只返回char的动态数组:
char* get(int i) {
        if (i >= len) {
            return "";
        } else {
            return list[i];
        }
    }下面是我的类SList私有变量:
private:
    char** list;
    int len;
    char* generateString(){
        char* str;
        int n = rand() % 20 + 1;
        str = new char[n + 1];
        for(int i = 0; i < n; i++) {
            str[i] = 'a' + rand()%26;
        }
        str[n] = '\0';
        return str;
    };~SList() {
        delete[] list;
    }它总是显示析构函数上的malloc错误。
malloc: *** error for object 0x105007410: pointer being freed was not allocated
malloc: *** set a breakpoint in malloc_error_break to debug请帮帮我!我仔细检查了动态分配数组上的delete方法,但是它总是显示这个错误。
我试过检查其他函数中的其他删除,但它们都没有犯相同的malloc错误。我尝试过注释析构函数方法,一切都很好。但我真的需要用析构方法。我希望在c++方面拥有更多专业知识的人能够帮助我修复这个malloc错误,并解释我犯了什么错误。
发布于 2022-03-24 06:56:02
不管实现的其他细节是什么,在使用称为"破烂阵列“的数据结构时,析构函数都是不正确的,也就是说,list是指向指针数组的指针。delete[]将释放指针数组,但不释放其元素指向的char数组。你必须这样做:
~SList() {
    if(!list) return;   // if we cannot guarantee that list isn't 
                        // nullptr we have to check it, 
                        // or result of list[i] would be undefined. 
    for(int i = 0; i < len; i++) 
        delete[] list[i];
    delete[] list;
}并且您必须确保这些指针中的任何一个都是由new表达式初始化的或等于nullptr。它不是靠自己发生的。你必须确保在施工和所有操作过程中。你什么都没出现。在那里找毛病。
get()方法是一种等待发生的灾难,是一种不符合C++规则的错误形式。字符串文本""总是返回const char*,并且语句return "";是不正确的-一些编译器只是对此发出警告。它不能被delete释放。
char* get(int i) {
    if (i >= len) {
        return nullptr;  // "" - is not safe
    } else {
        return list[i];
    }
}删除nullptr是一个安全的不操作。删除new没有返回的内容是一场灾难。
加法运算符按值取list2,这意味着必须实现正确的复制操作。你也没给他们看。默认实现只是复制一个指针,本地副本的销毁将释放原来通过上面的~SList()使用的内存。操作符必须返回结果对象,不应该修改this指出的对象。您已经实现了一个operator+=。你这样做,它的作用就像
 a+b;  // a now contains result of concatenation.用起来很奇怪。适当的操作者是
SList operator+(SList& list2);通常,处理某些资源的所有权的对象(在我们的例子中是动态内存)必须实现某些特殊的成员函数集:
 ~SList();
 SList(const SList& other);
 SList(SList&& other); // move copy, source is a temporal.
 SList& operator=(const SList& other);
 SList& operator=(SList&& other); // move assignment如果这样做正确,您可以安全地完成c = a + b;分配。
请注意,如果通过引用传递参数,则必须考虑赋值运算符的参数没有引用this指出的对象,如果它们引用了对象,则相应地执行操作。否则你会毁了它并丢失原始数据。另一方面,由于成本和内存占用增加,复制参数过多且对用户不友好。N元素和m元素数组的级联应该具有n+m元素的内存占用,而不是n+2*m。
https://stackoverflow.com/questions/71597537
复制相似问题