编译器错误“未分配的指针未分配”仅在 C++ 中使用自定义对象的 foreach 循环时

Compiler error "Pointer being freed was not allocated" only while using a foreach loop of custom objects in C++

提问人:BrownBear2018 提问时间:10/13/2021 最后编辑:BrownBear2018 更新时间:10/13/2021 访问量:53

问:

我有一个作业,我构建了自己的字符串类。我制作了几个 MYString 对象并将它们放在一个向量中。当我通过下标运算符访问向量时,我没有问题。但是当我使用 foreach 循环遍历向量时,我得到一个奇怪的错误“”未分配被释放的指针”

  1. 我搞砸了我的复制构造函数吗?
  2. 我的析构函数和 clear() 函数搞砸了吗?

头文件如下:


    class MYString{
        friend std::ostream& operator<<(std::ostream&, const MYString&);
        friend std::istream& operator>>(std::istream&, MYString&);
        private:
            static const int INITIAL_CAP = 20;
            char* str;
            static int getLength(const char*);
            int cap;  //capacity of the char array, in multiples of 20
            int end;  // location of the null terminator
            int compareTo(const MYString& rhs);
            void clear();  // to manually free memory
            static int requiredCap(int end);
        
        public:
            MYString();
            MYString(const MYString& mystr);
            MYString(const char*);
            ~MYString();
    
            MYString& operator=(const MYString& rhs);
            char& operator[](int index);
            const char& operator[](int index) const;
    
            int length() const;
            int capacity() const;
            const char* c_str();
    
            MYString operator+(const MYString& rhs);
    
            int operator==(const MYString& rhs);
            int operator>(const MYString& rhs);
            int operator<(const MYString& rhs);
    };

Here is some relevant function defintions

MYString::MYString(const MYString& rhs){
    *this = rhs;
}

MYString& MYString::operator=(const MYString& rhs){
    if (this == &rhs){
        return *this;
    }

    clear();
    cap = rhs.cap;
    end = rhs.end;
    str = new char[cap];

    for (int i = 0; i < end; i++){
        str[i] = rhs[i];
    }

    str[end] = '\0';
    return *this;
}

MYString::~MYString(){
    clear();
}

void MYString::clear(){
    cap = 0;
    end = 0;
    delete[] str;
    str = nullptr;
}

The main method is as follows:

#include "MYString.h"
#include <iostream>
#include <vector>
#include <fstream>

using namespace std;

int main(){

    ifstream input;
    input.open("file.txt");
    if (input.fail()){
        cout << "File error" << endl;
    }


    MYString s;

    vector<MYString> v;
    int count = 0;
    v.push_back(MYString());
    int index = 0;
    while (input >> s){
        if (count == 2){
            v.push_back(MYString());
            count = 0;
            index++;
        }
        if (count < 2){
        v[index] = v[index] + s;
        count++;
        }
    }
    
    for (MYString& str : v){
        cout << str << endl;
    }

C++ 指针 向量 C++17 复制构造函数

评论

0赞 001 10/13/2021
您将 4 个字符串放入向量中,但尝试读取 5 的 。cout << v[4] << endl;
0赞 10/13/2021
您的复制构造函数调用它将调用未初始化的(因为它不是默认的clear()delete[]strnullptr)
0赞 BrownBear2018 10/13/2021
我修复了我的主要方法。要点是,如果我使用 foreach 循环并通过引用访问该值,它会起作用;但是如果我按值访问,那么我会得到一个奇怪的错误。原因是什么?

答:

0赞 Chris Uzdavinis 10/13/2021 #1

构造函数存在严重问题:

MYString::MYString(const MYString& rhs){
    *this = rhs;
}

在对象的主体中,您的数据不会初始化,但您可以取消引用并分配给它。数据成员包含垃圾,包括指针。在赋值运算符中,调用 clear,这将调用此垃圾指针。这是未定义的行为。delete[]

在赋值方面实现构造函数总是错误的。赋值用于将初始化对象的状态替换为新状态,而构造函数则为未初始化的成员提供初始状态。在构造函数完成之前,对象的生存期甚至还没有开始。在生命尚未正式开始的对象上调用函数是未定义的行为。

复制构造函数需要分配内存并将数据复制到内存中,这与在赋值运算符中执行的操作类似,但不会先清理旧状态。此外,请考虑使用 strcpy 而不是循环来复制字节。它会更快。