При выполнении деструктора краш программы

Рейтинг: 0Ответов: 1Опубликовано: 06.03.2023

Есть у меня код

Abiturient.h

#pragma once
#include <iostream>
#include <string>

using namespace std;

struct Object{
    string object;
    unsigned int rating;
};

class Abiturient{
private:
    string name;
    string surname;
    unsigned int count_objects;
    Object* objects;
public:
    Abiturient();
    ~Abiturient();

    void input();

    friend class List;
};

class List{
private:
    Abiturient* list;
    unsigned int size;
public:
    List(unsigned int);
    ~List();

};

Abiturient.cpp


#include "Abiturient.h"


Abiturient::Abiturient(){
    name = string();
    surname = string();
}

Abiturient::~Abiturient(){
    delete[] objects;
}

void Abiturient::input(){
    cout << "Ввод данных абитуриента" << endl;
    cout << "Введите имя: ";
    cin >> name;
    cout << "Введите фамилию: ";
    cin >> surname;
    cout << "Введите кол-во предметов: ";
    cin >> count_objects;

    objects = new Object[count_objects];
    for(unsigned int i = 0; i < count_objects; i++){
        cout << "Введите название " << i + 1 << "-его предмета: ";
        cin.ignore();
        getline(cin,objects[i].object);
        cout << "Введите бал: ";
        cin >> objects[i].rating;
    }
}

List::List(unsigned int size){
    this->size = size;
    list = new Abiturient[this->size];
}

List::~List(){
    delete[] list;
}

main.cpp


#include "Abiturient.h"

int main(){

        setlocale(LC_ALL,"Ukrainian");
    
        unsigned int size;
        cout << "Введите кол-во абитуриентов: ";
        cin >> size;
    
        List lst(size);
    
        
        return 0;
    }

Понимаю что скорее всего проблема в деструкторе и динамической памяти,но не могу разобратся что именно сделал не так,прошу помощи

Ответы

▲ 2Принят

Как абсолютно правильно написал Юрий Козлов, у вас new для objects вызывается в Abiturient::input(). А её вы в коде не вызываете. Поэтому в деструкторе ~Abiturient() вызывается delete[] для неинициализированного указателя Object* objects;.
Как быстрый вариант решения - обнулите указатель в конструкторе. Функция delete[] для нулевого указателя не делает ничего.

Abiturient::Abiturient(): objects(nullptr) {}

Abiturient::~Abiturient(){
    delete[] objects;
}

Кроме того, поскольку вы в деструкторе управляете ресурсом, чтобы избежать в дальнейшем множества ошибок, связанным с разделением владения ресурсом, вам необходимо следовать правило Пяти. С существующим кодом у вас опять будут ошибки по доступу к памяти после любого копирования объекта Abiturient.
Но вообще, лучше следовать идиоме управления ресурсами RAII (resource aquitization is initialization) - в конструкторе создавать ресурс (захватывать), в деструкторе - освобождать. Для этого в С++ сделали классы умных указателей unique_ptr<>.

class Abiturient{
private:
    std::unique_ptr<Object> objects{};

А ещё лучше, если вы вместо ручной работы с памятью, будете пользоваться контейнерами STL

class Abiturient{
private:
    std::vector<Object> objects;