Вылетает необрабатываемая ошибка
class Matrix{
private:
int** v;
int size;
Matrix merge(Matrix c11, Matrix c12, Matrix c21, Matrix c22){
Matrix m(size);
int cursize = size/2;
for(int i = 0; i < cursize; i++){
for(int j = 0; j < cursize; j++){
m(i, j) = c11(i,j);
m(i+cursize,j) = c21(i, j);
m(i,j+cursize) = c12(i, j);
m(i+cursize,j+cursize) = c22(i, j);
}
}
return m;
}
public:
static bool added;
Matrix() : size(0){}
Matrix(int s) : size(s){
v = new int*[size];
for(int i = 0; i < size; i++){
v[i] = new int[size];
}
}
Matrix(Matrix m, const int index1, const int index2){
size = m.size/2;
v = new int*[size];
for(int i = 0; i < size; i++){
v[i] = new int[size];
}
for(int i = index1; i-index1<size; i++ ){
for(int j = index2; j -index2<size; j++){
int item= m(i, j);
v[i-index1][j-index2]=item;
}
}
}
void getMatrix(){
int n = size;
if(n%2!=0){
size++;
added = true;
}
v = new int*[size];
for(int i = 0; i < size; i++){
v[i] = new int[size];
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
v[i][j] = rand()%100;
}
}
}
void display() const{
int n = added? size-1: size;
for(int i = 0; i <n; i++){
for(int j = 0; j<n; j++){
cout << v[i][j] << " ";
}
cout << endl;
}
}
int& operator()(const int index1,const int index2){
return v[index1][index2];
}
Matrix operator+(Matrix m){
Matrix r(size);
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
r(i,j)= v[i][j] + m(i, j);
}
}
return r;
}
Matrix operator-(Matrix m){
Matrix r(size);
for(int i = 0; i<size; i++){
for(int j = 0; j< size; j++){
r(i, j) = v[i][j]-m(i, j);
}
}
return r;
}
Matrix simpleMultiplication(Matrix m){
Matrix res(size);
int prom = 0;
for(int i = 0; i <size; i++){
for(int j = 0; j < size; j++){
for(int k = 0; k<size; k++){
prom+= v[i][k] * m(k, j);
}
res(i, j) = prom;
}
}
return res;
}
Matrix operator*(Matrix B){
if(size == 1){
Matrix m(size);
m(0,0) = v[0][0] * B(0, 0);
return m;
}
// init of base matrixes
Matrix A11(*this, 0, 0);
Matrix A12(*this, 0, size/2);
Matrix A21(*this, size/2, 0);
Matrix A22(*this, size/2, size/2);
Matrix B11(B, 0, 0);
Matrix B12(B, 0, size/2);
Matrix B21(B, size/2, 0);
Matrix B22(B, size/2, size/2);
// end of init
//prom matrixes S
Matrix s1 = A21 + A22;
Matrix s2 = s1 - A11;
Matrix s3 = A11 - A21;
Matrix s4 = A12 - s2;
Matrix s5 = B12 - B11;
Matrix s6 = B22 - s5;
Matrix s7 = B22 - B12;
Matrix s8 = s6 - B21;
// end of prom matrixes
Matrix p1 = s2 * s6;
Matrix p2 = A11 * B11;
Matrix p3 = A12 * B21;
Matrix p4 = s3 * s7;
Matrix p5 = s1 * s5;
Matrix p6 = s4 * B22;
Matrix p7= A22 *s8;
Matrix t1 = p1+p2;
Matrix t2 = t1+p4;
Matrix c11 = p2+p3;
Matrix c12 = t1+p5+p6;
Matrix c21 = t2 - p7;
Matrix c22 = t2 + p5;
return merge(c11, c12, c21, c22);
}
};
class Test{
private:
int matrixSizes[6] = {4, 16, 32, 64,128,256};
public:
void getTests(){
for(int size : matrixSizes){
clock_t average1 = 0;
clock_t average2 = 0;
for(int i = 0; i < 1; i++) {
Matrix m1(size);
m1.getMatrix();
Matrix m2(size);
m2.getMatrix();
clock_t start1 = clock();
Matrix m = m1*m2;
clock_t finish1 = clock() - start1;
clock_t start2 = clock();
m = m1.simpleMultiplication(m2);
clock_t finish2 = clock() - start2;
average1+=finish1;
average2+=finish2;
}
cout << "For size of matrix: " << size << endl;
cout <<"Time in seconds for shtrassen alghoritm: " << average1*1.0/CLOCKS_PER_SEC << endl;
cout <<"Time in seconds for simple alghoritm: " << average2*1.0/CLOCKS_PER_SEC << endl;
}
}
};
bool Matrix::added = false;
int main() {
Test t;
t.getTests();
return 0;
}
Не знаю ответит ли кто, моя проблема что на тесте когда размер матрицы 256 вылетает необрабатываемая ошибка и я не могу даже догадаться почему.
Ответы (1 шт):
Фууух изрядно пришлось попотеть, но вроде все работает и ошибок не вылетает (но мог ошибиться т.к. пришлось переделывать ваш код, так что мог чего-то не доглядеть).
Начнем с изменений функций, а точней изменений их заголовков:
Функция
mergeMatrix merge(const Matrix& c11, const Matrix& c12, const Matrix& c21, const Matrix& c22) constДа не обязательно впихивать
const, но чтобы точно никаких ошибок больше не вылетало, лучше сделать.Думаю понятно, что мы принимаем 4 матрицы, который не изменяются в этой функции (чтобы не вызывались всякие конструкторы лишние добавляем ссылки), и возвращаем склеенную матрицу.
Я все таки добавил
v(nullptr)в конструктор по умолчанию:Matrix() : size(0), v(nullptr) {}В этом же пункте напишу, что добавил
constв конструктореMatrix(const Matrix& m, const int index1, const int index2)Функция
getMatrix()Тут я все таки изменил и саму функцию.
Заголовок функции:
void getMatirx(int size)то есть функция принимает размер матрицы, внутри себя инициализируетthis->size = sizeи выделяет память под матрицу, заполняя её случайными числами.А в функции
getTestsпишуMatrix m1;иMatrix m2;, т.к. до этого у вас вызывались конструкторы по умолчанию, выделялась память, а потом вызывалась функция в которой выделенная память затиралась, что приводило к утечке памяти.this->size = size; v = new int* [size]; for (int i = 0; i < size; i++) { v[i] = new int[size]; }int& operator() (const int index1, const int index2) constтут без комментариев, просто добавилconst.Так же добавил конструктор перемещения.
Тут я не стану расписывать зачем он нужен, но можете почитать тут
Matrix(Matrix&& m) { this->v = m.v; this->size = m.size; m.v = nullptr; m.size = 0; }И тут самое важное, я добавил деструктор. Раньше если поставить точку останова, в момент когда умножается матрицы 256 на 256, то можно увидеть в
Visual Studioчто память процесса занимала где-то 2 гб и все больше росло.Это как раз потому, что вы не очищали память, и у вас очень много создавалось экземпляров из-за чего происходила массовая утечка памяти :)
~Matrix() { if(v != nullptr) for (int i = 0; i < size; ++i) delete[] v[i]; delete[] v; v = nullptr; size = 0; }Дальше в один пункт засуну изменения заголовков у перегрузок операторов. Очень хорошая статься на habr по этой теме. Рекомендую почитать.
const Matrix operator+(const Matrix& m) constТакие же изменения произошли у оператора
-и*.Так же добавил оператор присваивания:
Matrix& operator =(const Matrix& other) { if (this == &other || other.v == nullptr) return *this; this->~Matrix(); v = new int* [other.size]; for (int i = 0; i < other.size; ++i) { v[i] = new int[other.size]; for (int j = 0; j < other.size; ++j) v[i][j] = other.v[i][j]; } size = other.size; return *this; }Тут хотелось бы сказать о том, что есть правило трех и правило пяти, но ... В общем рекомендую ознакомиться и лучше это правило соблюдать конечно :) Вот ссылка на википедию на русском и все максимально понятно написано.
Ну и последнее маленькое изменение:
Matrix simpleMultiplication(const Matrix& m) const
В общем надеюсь я вам помог и нигде не ошибся. Вот полный код Удачи!