При выполнении деструктора краш программы
Есть у меня код
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;
}
Понимаю что скорее всего проблема в деструкторе и динамической памяти,но не могу разобратся что именно сделал не так,прошу помощи
Ответы (1 шт):
Как абсолютно правильно написал Юрий Козлов, у вас 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;