c++ - 在双数组的 calloc 上写入大小为 8 的无效
问题描述
我不想在这里问它,但我几乎没有选择。
我有一个矩阵结构
#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)
该错误不是系统性的,并且发生在代码的第二次初始化时。这促使我对其进行测试,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.
解决方案
grad_p_f->mat[9] = 1;
分配数组后不久的写入超出范围。您的数组是 3*3=9 元素,索引从 0 开始(因此有效下标包括 0..8)。
此写入超出了calloc
调用分配的内存的末尾,并由 valgrind 报告。
我认为你所有的下标都减了一个。
推荐阅读
- excel - 绕过我的代码中 255 个字符限制的方法?
- vue.js - Bootstrap-vue:如何显示所选项目的文本?
- angular7 - 从承诺中保存在服务中的数据之后无法访问
- java - 程序将在 Netbeans 11.2 上构建,但 jar 文件不会做它应该做的事情
- php - Laravel 仅使用手机号码注册/登录
- javascript - 如何将 flowJS 类型添加到自定义 Web 组件?
- mongodb - MERN堆栈二进制图像只是一个黑色方块
- python - 尽管代码正常运行,但将约会上传到 Outlook 日历时出现 Python 属性错误
- javascript - React Native 动态构建树
- android - 在 SVG 中反应原生编辑路径