Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
201 views
in Technique[技术] by (71.8m points)

c++ - What is the problem with appending arbitrary object to the array?

I have a simple program that process strings from a file into arbitrary class Student (provided below) and appends it to self-written container ArraySequence. When error almost always occurs on marked line (marked with *****).

Class Student:

class Student {
public:
    int year;
    std::string name;
    std::string surname;
    Student(int _year, std::string _name, std::string _surname) {
        this->year = _year;
        this->name = _name;
        this->surname = _surname;
    }
    Student(const Student& s) {
        this->year = s.year;
        this->name = s.name;
        this->surname = s.surname;
    }
    Student& operator=(const Student& s) {
        this->year = s.year;
        this->name = s.name;
        this->surname = s.surname;
        return *this;
    }
    bool operator==(const Student& s) const {
        if (this->year == s.year && this->name == s.name && this->surname == s.surname)
            return true;
        return false;
    }
};

main:

int main() {
    std::ifstream data("filename");
    std::string buffer;
    ArraySequence<Student>* entities = new ArraySequence<Student>;

    getline(data, buffer, '
');
    while (buffer.size() != 0) {
        std::cout << buffer << std::endl;
        int len = static_cast<int>(buffer.find(" "));
        std::string surname = buffer.substr(0, len);
        buffer = buffer.substr(len + 1);
        len = static_cast<int>(buffer.find(" "));
        std::string name = buffer.substr(0, len);
        int year = std::stoi(buffer.substr(len + 1));
        Student b(year, name, surname);
        entities->append(b); *****
        getline(data, buffer, '
');
    }

    std::cout << count << std::endl;

Append:

template <typename T>
void ArraySequence<T>::append(const T& item) {
    ISequence<T>::length++;
    if (!(ISequence<T>::length - 1)) {
        data = (T*)malloc(sizeof(T));
    }
    else {
        data = (T*)realloc(data, sizeof(T) * ISequence<T>::length);
    }
    *(data + ISequence<T>::length - 1) = item;
}

Errors: Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT); Thread 1: EXC_BAD_ACCESS (code=1, address=0x3);

Sometimes it would just work, but other times it crashes with errors.

I'm using Xcode 11.1

In Thread 1 it says that problem with operator= of Student on the line c++ this->surname = s.surname;

What can I do in a situation like this? Any ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

T consists of a non-trivial type (Student contains std::string, plus non-trivial copy/ assignment and destructor), using malloc and realloc will not work correctly.

malloc and realloc do not create viable objects. They only allocate memory. Your program likely crashes due to these invalid Student objects.

The easiest solution is to rewrite ArraySequence<T>::append to only use new[] and delete[], not malloc and realloc.

Note: malloc can be used when using placement-new, but you were not using malloc for this purpose.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...