#c #heap-corruption
#c #повреждение кучи
Вопрос:
Я создаю класс динамического массива, который содержит многочлены. Проблема, с которой я сталкиваюсь прямо сейчас, заключается в том, что когда я запускаю свой код, как только он попадает в инструкцию return в main, он начинает вызывать деструктор и начинает освобождать память от каждого экземпляра, начинающегося с C. Он удаляет C нормально, но когда он доходит до B, я получаю ошибку повреждения кучи. Я попытался просмотреть код, но я не могу увидеть, где происходит повреждение. Кто-нибудь может мне помочь? Точная ошибка, которую это выдает, заключается в том, что «CRT обнаружил, что приложение записало в память после завершения буфера кучи».
* Редактировать: Я более чем рад получить рекомендации пользователей, которые помогут улучшить мой код, но помните, что это для класса и имеет определенные правила. Я не могу использовать что-либо из STL. Мне нравится любая критика, которую вы можете мне высказать.
/////////////////////////// Заголовок/////////////////////////////
class Poly
{
friend std::ostreamamp; operator<<(std::ostreamamp; output, const Polyamp; pNomial);
public:
Poly();
Poly(const intamp; coeff, const intamp; degree = 0);
Poly(const Polyamp; copy);
~Poly();
void setCoeff(const intamp; coeff, const intamp; degree);
bool isEmpty()const;
Polyamp; operator=(const Polyamp; pNomial);
private:
int* coeffs;
int highestDegree;
};
///////////////////////////CPP////////////////////////
#include "poly.h"
Poly::Poly()
{
highestDegree = 0;
coeffs = new int[highestDegree 1]();
}
Poly::Poly(const int amp; coeff, const int amp; degree)
{
if (degree >= 0)
{
highestDegree = degree;
coeffs = new int[highestDegree 1]();
coeffs[degree] = coeff;
}
else
{
highestDegree = 0;
coeffs = new int[highestDegree 1]();
}
}
Poly::Poly(const Polyamp; copy)
{
highestDegree = copy.highestDegree;
coeffs = new int[highestDegree 1]();
for (int i = 0; i < copy.highestDegree 1; i )
{
coeffs[i] = copy.coeffs[i];
}
}
Poly::~Poly()
{
delete[] coeffs;
}
void Poly::setCoeff(const intamp; coeff, const intamp; degree)
{
if (degree > this->highestDegree)
{
Poly temp = *this;
delete[] this->coeffs;
this->highestDegree = degree;
this->coeffs = new int[highestDegree]();
for (int i = 0; i < temp.highestDegree 1; i )
{
this->coeffs[i] = temp.coeffs[i];
}
}
if (degree >= 0)
{
this->coeffs[degree] = coeff;
}
}
bool Poly::isEmpty()const
{
bool check = true;
for (int i = 0; i < highestDegree 1 amp;amp; check; i )
{
if (coeffs[i] != 0)
{
check = false;
}
}
return check;
}
Poly amp; Poly::operator=(const Polyamp; pNomial)
{
if (this != amp;pNomial)
{
delete[] this->coeffs;
this->highestDegree = pNomial.highestDegree;
this->coeffs = new int[this->highestDegree 1]();
for (int i = 0; i < pNomial.highestDegree 1; i )
{
this->coeffs[i] = pNomial.coeffs[i];
}
}
return *this;
}
std::ostreamamp; operator<<(std::ostreamamp; output, const Polyamp; poly)
{
if (!poly.isEmpty())
{
for (int i = poly.highestDegree; i >= 0; i--)
{
if (i == 1 amp;amp; poly.coeffs[i] != 0)
{
if (poly.coeffs[i] >= 1)
{
output << " " << poly.coeffs[i] << "x";
}
else
{
output << " " << poly.coeffs[i] << "x";
}
}
else if (i == 0 amp;amp; poly.coeffs[i] != 0)
{
if (poly.coeffs[i] >= 1)
{
output << " " << poly.coeffs[i];
}
else
{
output << " " << poly.coeffs[i];
}
}
else if (poly.coeffs[i] != 0)
{
if (poly.coeffs[i] >= 1)
{
output << " " << poly.coeffs[i] << "x^" << i;
}
else
{
output << " " << poly.coeffs[i] << "x^" << i;
}
}
}
}
else
{
output << " 0";
}
return output;
}``
/////////////////////////////////Main/////////////////////////
#include "poly.h"
#include <iostream>
int main()
{
Poly A, B(5, 7), C(2);
B.setCoeff(2, 10);
B.setCoeff(1, 3);
B.setCoeff(5, 4);
std::cout << A << std::endl;
std::cout << B << std::endl;
std::cout << C << std::endl;
return 0;
}
Комментарии:
1. Прежде чем вы даже подумаете о ее решении, загляните глубоко внутрь и задайте себе один вопрос.
Why didn't I use a vector?
2. Смысл моего проекта в том, чтобы создать свой собственный класс dynamic array и не использовать STL.
3. ` for (int i = poly.highestDegree; i >= 0; i—) { if (i == 1 amp;amp; poly.coeffs[i] != 0)` Насколько велик ваш массив еще раз?
4. Вы нарушаете принцип единой ответственности.
Poly
отвечает за надлежащее управление временем жизниcoeff
, а также за множество других вещей. Ничего хорошего из этого не выйдет. Если вы хотите изобрести велосипед для образовательных целей, тогда создайте класс, который абстрагирует управление временем жизни объекта dynamic storage duration (он жеstd::unique_ptr
). Затем создайте класс, который абстрагирует вектор (он будет использовать предыдущий класс) (он жеstd::vector
). Затем, наконец, создайте свойPoly
класс (который будет использовать класс vector).5. @Vuwox Кажется, что с добавлением более новых компиляторов
()
после array new данные будут инициализироваться.
Ответ №1:
Я должен сказать, что я согласен с комментариями, и вам следует серьезно заняться надлежащим управлением временем жизни ресурсов, которые вы используете в Poly
классе. Чтобы ответить на проблему, с которой вы столкнулись, взгляните на setCoeff()
функцию.
this->coeffs = new int[highestDegree]();
должно быть изменено на,
this->coeffs = new int[highestDegree 1]();
В вашей текущей реализации вы выделяете массив с помощью highestDegree
и в вашем for
цикле вы получаете доступ temp.coeffs[highestDegree]
к тому, что находится за пределами доступа, т. е. вы выполняете цикл до i < temp.highestDegree 1
.
Комментарии:
1. Можете ли вы подробнее рассказать о правильном управлении ресурсами в течение всего срока службы?
2. Спасибо, я не могу поверить, что я это упустил. У вас случайно нет ссылки, которая четко объясняет правильное управление ресурсами в течение всего срока службы? Я никогда не слышал об этом до сегодняшнего дня, и я всегда стремлюсь узнать больше.
3. Я понимаю, что вы не можете использовать STL, но вы все равно можете использовать shared_ptr для массива, т. Е. что-то вроде
std::shared_ptr<int[]> coeffs
, что значительно уменьшит накладные расходы на удаление объектов вручную, поскольку время жизни coeffs теперь привязано кshared_ptr
объекту, который уничтожит базовые ресурсы при уничтожении shared_ptr. В терминах C это называетсяRAII
. Кроме того, вам следует подумать о том, чтобы выполнить очистку вашего кода, поскольку в настоящее время он содержит неиспользуемые параметры и т.д.4. Спасибо, это было действительно очень полезно.
5. Вы также можете использовать
unique_ptr
просто для добавления некоторой информации, но вам нужно выполнить глубокое копирование самостоятельно в конструкторе копирования, посколькуunique_ptr
сами по себе они не копируются. Надеюсь, это поможет.