Проблемы с деструктором — ошибка: Выражение: _BLOCK_TYPE_IS_VALID_ (pHead-> gB ;UB)

Я дал этому классную гистограмму, и я динамически распределяю память для своего класса. У меня проблемы с деструктором. Ошибка:

Выражение: _BLOCK_TYPE_IS_VALID_ (pHead-> pBlockUse)

Что я делаю не так?

histogram.h

 #ifndef HISTOGRAM_H
#define HISTOGRAM_H
#include<iostream>
class Histogram
{
private:
int** matrix;
int lines;
double* normalizedArray;
int *values;
void SortMatrix();
public:
Histogram(int elements[], int elementsNr);
Histogram(int** matrix, int lines);
void Normalize();
void PrintNormalized();
void PrintDenormalized();
void PrintValues();
void PrintNormalizedArray();
int* GetValues() const {return values;}
double* GetNormalizedArray() const {return normalizedArray;}
int GetLines() const {return lines;}
double CalculateD1(Histogram histo);
double CalculateD2(Histogram histo);
double CalculateIntersection(Histogram hist);
~Histogram(){
delete []matrix;
delete []normalizedArray;
delete []values;
}
};
#endif
histogram.cpp

#include<math.h>
#include"histogram.h"using namespace std;
Histogram::Histogram(int** m, int l)
{
lines=l;
normalizedArray=NULL;
values=NULL;
matrix=new int*[lines];
for(int i=0;i<lines;i++)
{
matrix[i]=new int[2];
}
for(int i=0;i<lines;i++)
{
matrix[i][0]=m[i][0];
matrix[i][1]=m[i][1];
}

SortMatrix();
//save the values
values=new int[lines];
for(int i=0;i<lines;i++)
{
values[i]=matrix[i][0];
}
}

Histogram::Histogram(int elements[], int elementsNr)
{
lines=0;
normalizedArray=NULL;
//initialize matrix : elementrNr lines and 2 columns
matrix=new int*[elementsNr];
for(int i=0;i<elementsNr;i++)
{
matrix[i]=new int[2];
matrix[i][0]=INT_MIN;
matrix[i][1]=INT_MIN;
}
//search each element from the array in the matrix
bool found=false;
for(int i=0;i<elementsNr;i++)
{
found=false;
for(int j=0;j<elementsNr;j++)
{
//the element was found in the matrix ( on the first column )
if(matrix[j][0] == elements[i])
{
matrix[j][1]++;
found=true;
break;
}
}
if(!found)
{
matrix[lines][0]=elements[i];
matrix[lines][1]=1;
lines++;
}
}
SortMatrix();
//save the values
values=new int[lines];
for(int i=0;i<lines;i++)
{
values[i]=matrix[i][0];
}

}
void Histogram::SortMatrix()
{

for(int i=0;i<lines;i++)
{
for(int j=0;j<lines-1;j++)
{
if(matrix[j][0]>matrix[j+1][0])
{
int temp = matrix[j+1][0];
matrix[j+1][0] = matrix[j][0];
matrix[j][0] = temp;
}
}
}
}

void Histogram::PrintDenormalized()
{
for(int i=0;i<lines;i++)
{
cout<<matrix[i][0]<<" : " <<matrix[i][1]<<endl;
}

}
void Histogram::PrintNormalized()
{
for(int i=0;i<lines;i++)
{
cout<<matrix[i][0]<<" : "<<normalizedArray[i]<<endl;
}
}

void Histogram::PrintValues()
{
for(int i=0;i<lines;i++)
{
cout<<values[i]<<endl;
}
}
void Histogram::PrintNormalizedArray()
{
for(int i=0;i<lines;i++)
{
cout<<normalizedArray[i]<<endl;
}
}

void Histogram::Normalize()
{
int N=0;
normalizedArray=new double[lines];
for(int i=0;i<lines;i++)
{
N+=matrix[i][1];
}
for(int i=0;i<lines;i++)
{
normalizedArray[i]=static_cast<double>(matrix[i][1])/N;
}
}

double Histogram::CalculateD1(Histogram histo)
{
//the two histograms must have the same values
int* values2 = histo.GetValues();
int lines2 = histo.GetLines();
if(lines!=lines2)
{
return -1;
}
for(int i=0;i<lines;i++)
{
if(values[i]!=values2[i])
{
return -1;
}
}

//if we got this far the two histograms have the same values, so we can calculate the distance
double* normalizedArray2=histo.GetNormalizedArray();
double dist=0.0;
for(int i=0;i<lines;i++)
{
dist +=  abs(normalizedArray[i]-normalizedArray2[i]);
}
return dist;
}

double Histogram::CalculateD2(Histogram histo)
{
//the two histograms must have the same values
int* values2 = histo.GetValues();
int lines2 = histo.GetLines();
if(lines!=lines2)
{
return -1;
}
for(int i=0;i<lines;i++)
{
if(values[i]!=values2[i])
{
return -1;
}
}

//if we got this far the two histograms have the same values, so we can calculate the distance
double* normalizedArray2=histo.GetNormalizedArray();
double dist=0.0;
for(int i=0;i<lines;i++)
{
dist +=  pow(normalizedArray[i]-normalizedArray2[i], 2);
}
return sqrt(dist);
}

double Histogram::CalculateIntersection(Histogram histo)
{
//the two histograms must have the same values
int* values2 = histo.GetValues();
int lines2 = histo.GetLines();
if(lines!=lines2)
{
return -1;
}
for(int i=0;i<lines;i++)
{
if(values[i]!=values2[i])
{
return -1;
}
}

//if we got this far the two histograms have the same values, so we can calculate the intersection
double* normalizedArray2=histo.GetNormalizedArray();
double v1=0.0;
double v2=0.0;
for(int i=0;i<lines;i++)
{
v1 += normalizedArray[i] < normalizedArray2[i] ? normalizedArray[i] : normalizedArray2[i];
v2 += normalizedArray[i];
}
return v1/v2;
}

0

Решение

Ни один конструктор не инициализирует normalizedArray, Это означает, что вызов delete[] normalizedArray в деструкторе будет работать по унифицированному указателю. Исправить, инициализировать normalizedArray в каждом из конструкторов NULL, призвание delete[] (или же delete) на NULL Указатель в безопасности.

Как Histogram имеет динамически распределяемые члены, которые вам нужно либо предотвратить копирование:

class Histogram
{
Histogram(const Histogram&);
Histogram& operator=(const Histogram&);
};

или правильно реализовать конструктор копирования и оператор присваивания. Увидеть Что такое правило трех?
Экземпляры Histogram будут быть скопирован, если вызывается любая из следующих функций:

double CalculateD1(Histogram histo);         // Pass by const reference instead
double CalculateD2(Histogram histo);         // if the functions do not modify
double CalculateIntersection(Histogram hist) // their argument.

Если конструктор копирования и оператор присваивания не реализованы для классов, которые имеют динамически распределенную память, то два экземпляра класса в конечном итоге будут указывать на одну и ту же динамически распределенную память после операции копирования. Когда один из двух экземпляров уничтожен, он оставляет другой экземпляр с висячими указателями (указателями на память, которые больше не действительны). Любая попытка использовать это неопределенное поведение.


Если это не упражнение, используйте std::vector<>вместо. Он обрабатывает динамически выделенную память для вас:

std::vector<std::vector<int>> matrix;
std::vector<double> normalizedArray;
std::vector<int> values;
2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector