Неверная запись размера 8 на callo c двойного массива - PullRequest
0 голосов
/ 11 марта 2020

Я не хотел спрашивать это здесь, но у меня практически нет вариантов.

У меня есть матричная структура

#include <stdlib.h>
#include <math.h>

typedef struct Matrix{
  double *mat;
  int rows;
  int columns;
} Matrix;

, которую я инициализирую следующим образом

Matrix* init_Matrix(int rows, int columns) {
  Matrix *matrix = (Matrix*) malloc(sizeof(Matrix));

  matrix->rows = rows;
  matrix->columns = columns;
  matrix->mat = (double*) calloc(rows*columns, sizeof(double));

  return matrix;
}

Однако, когда я запустил его как часть более крупного кода, он выдал

malloc(): corrupted top size
Aborted (core dumped)

Ошибка не систематизирована c и возникает при второй инициализации в коде. Это побудило меня проверить его с помощью valgrind, который дал следующий вывод

==19211== Invalid write of size 8
==19211==    at 0x1096DF: odometer(Robot*, double, double, double) (main.cc:41)
==19211==    by 0x109B6F: main (main.cc:82)
==19211==  Address 0x4dcbe68 is 0 bytes after a block of size 72 alloc'd
==19211==    at 0x483CD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==19211==    by 0x109C33: init_Matrix(int, int) (matrix_gr7.cc:18)
==19211==    by 0x1095BD: odometer(Robot*, double, double, double) (main.cc:38)
==19211==    by 0x109B6F: main (main.cc:82)

Очевидно, что проблема calloc, но я не могу найти то, что сделал неправильно. У кого-нибудь есть идея?

РЕДАКТИРОВАТЬ: Добавление дополнительного кода для воспроизведения ошибок matrix_gr7.h

#include <stdlib.h>
#include <math.h>

typedef struct Matrix{
  double *mat;
  int rows;
  int columns;
} Matrix;

Matrix* init_Matrix(int rows, int columns);
void free_Matrix(Matrix *matrix);

Matrix* matrix_product(Matrix *a, Matrix *b);

Matrix* matrix_sum(Matrix *a, Matrix *b);

Matrix* matrix_transpose(Matrix *a);

void print_matrix(Matrix *a);

matrix_gr7.cc

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include "matrix_gr7.h"


Matrix* init_Matrix(int rows, int columns) {
  Matrix *matrix = (Matrix*) malloc(sizeof(Matrix));

  matrix->rows = rows;
  matrix->columns = columns;
  matrix->mat = new double[rows*columns];

  return matrix;
}

void free_Matrix(Matrix *matrix) {
  if (matrix != NULL) {
    if (matrix->mat != NULL) {
      free(matrix->mat);
    }
    free(matrix);
  }
}

Matrix* matrix_product(Matrix *a, Matrix *b) {
  Matrix *c = init_Matrix(a->rows, b->columns);

  double temp;

  for (int i = 0; i < a->rows; i++) {
    for (int j = 0; j < b->columns; j++) {
      temp = 0;
      for (int k = 0; k < a->columns; k++) {
        temp += (a->mat[k+(i*a->columns)])*(b->mat[j+(k*b->columns)]);
      }
      c->mat[i*(c->columns) + j] = temp;
    }
  }
  return c;
}

Matrix* matrix_sum(Matrix *a, Matrix *b) {
  Matrix *c = init_Matrix(a->rows, a->columns);
  for (int i = 0; i < a->rows*a->columns; i++) {
    c->mat[i] = a->mat[i] + b->mat[i];
  }
  return c;
}

Matrix* matrix_transpose(Matrix *m) {
  Matrix *n = init_Matrix(m->columns, m->rows);
  for (int i = 0; i < m->rows; i++) {
    for (int j = 0; j < m->columns; j++) {
      n->mat[i + j*n->columns] = m->mat[j + i*m->columns];
    }
  }
  return n;
}

void print_matrix(Matrix* m) {
  for (int i = 0; i < m->rows*m->columns; i++) {
    printf("%f  ,", m->mat[i]);
    if ((i+1)%m->columns  == 0) {
      printf("\n");
    }
  }
}

robot.h

#include "matrix_gr7.h"

typedef struct Robot {
  double x;
  double y;
  double th;
  Matrix *Sig_p;
  double last_t_update;
} Robot;

Robot* init_Robot(double x, double y, double th);

void free_Robot(Robot* robot);

robot.cc

#include "robot.h"
#include "matrix_gr7.h"

Robot* init_Robot(double x, double y, double th) {
  Robot* robot = (Robot*) malloc(sizeof(Robot));
  robot->x = x;
  robot->y = y;
  robot->th = th;
  robot->last_t_update = 0;
  robot->Sig_p = init_Matrix(3, 3);

  return robot;
}

void free_Robot(Robot* robot) {
  free_Matrix(robot->Sig_p);
  free(robot);
}

main.cc

#include <stdio.h>
#include <math.h>
#include "matrix_gr7.h"
#include "robot.h"

void odometer(Robot* cvs, double w_r, double w_l, double t) {
  Matrix *grad_p_f = init_Matrix(3, 3);
  grad_p_f->mat[7] = 0; grad_p_f->mat[8] = 0; grad_p_f->mat[9] = 1;

  Matrix *grad_p_f_T = matrix_transpose(grad_p_f);

  Matrix *grad_rl_f = init_Matrix(3, 2);
  grad_rl_f->mat[5] = 1.0/0.225;
  grad_rl_f->mat[6] = -1.0/0.225;

  Matrix *grad_rl_f_T = matrix_transpose(grad_rl_f);
  Matrix *Sig_rl = init_Matrix(2,2);

  Matrix *temp1 = matrix_product(grad_p_f, cvs->Sig_p);
  Matrix *temp2 = matrix_product(temp1, grad_p_f_T);
  Matrix *temp3 = matrix_product(grad_rl_f, Sig_rl);
  Matrix *temp4 = matrix_product(temp4, grad_rl_f_T);

  free_Matrix(cvs->Sig_p);
  cvs->Sig_p = matrix_sum(temp2, temp4);

  free_Matrix(grad_p_f); free_Matrix(grad_p_f_T); free_Matrix(Sig_rl);
  free_Matrix(grad_rl_f); free_Matrix(grad_rl_f_T);
  free_Matrix(temp1); free_Matrix(temp2);
  free_Matrix(temp3); free_Matrix(temp4);
  cvs->last_t_update = t;
}

int main() {
  Robot* robot = init_Robot(0, 0, 0);

  odometer(robot, 1, 1, 1);
  matrix_transpose(robot->Sig_p);

  free_Robot(robot);

  return 0;
}

The program fails at the `Matrix *grad_p_f_T = matrix_transpose(grad_p_f);` line but `valgrind` shows memory issues way before that.

1 Ответ

0 голосов
/ 11 марта 2020

Запись в grad_p_f->mat[9] = 1; вскоре после выделения массива выходит за пределы. Ваш массив состоит из 3 * 3 = 9 элементов, и индексирование начинается с 0 (поэтому допустимые подписки - 0,8 включительно).

Эта запись находится за концом памяти, выделенной вызовом calloc, и сообщается valgrind.

Я думаю, что все ваши подписчики отключены на один.

...