我正在尝试创建一个函数来初始化具有n * n维和元素数组的Matrix结构。但是,无法将数组中传递给函数的值正确分配给矩阵中的数组(请参见输出)。
是什么原因导致此问题,并且有更好的方法来解决此问题?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int rows;
int cols;
double *data;
} Matrix;
Matrix loadMatrix(int rows, int cols, double *data); //initialise matrix with elements in 'data'
void printMatrix(Matrix m);
int main(void) {
double data[4] = {1,2,3,4};
Matrix m = loadMatrix(2, 2, data);
printMatrix(m);
free(m.data);
return 0;
}
Matrix loadMatrix(int rows, int cols, double * elements)
{
Matrix result;
result.rows = rows;
result.cols = cols;
result.data = (double *)calloc(rows * cols, sizeof(double));
for(int i = 0; i < rows * cols; i++) {
*result.data = *elements; //copy each element to Matrix instance
result.data++;
elements++;
}
return result;
}
void printMatrix(Matrix m)
{
printf("\nRows: %d\tColumns: %d\n", m.rows, m.cols);
for(int i = 0; i < m.rows; i++) {
for(int j = 0; j < m.cols; j++) {
printf("%.0lf ", *m.data);
m.data++;
}
printf("\n");
}
}
输出
Rows: 2 Columns: 2
0 0
0 0
double free or corruption (out)
exit status -1
答案 0 :(得分:3)
您通过在result.data
中递增指针来破坏loadMatrix
指针。当您尝试打印或释放它时,它不再指向已分配内存的开始。
用数组索引替换指针的算术废话,以避免弄乱指针并使代码更简单:
for(int i = 0; i < rows * cols; i++) {
result.data[i] = elements[i];
}
请注意,您在printMatrix
函数中存在相同的问题,但是由于您没有返回修改后的副本,因此它在代码中没有任何作用。我还是建议在那里也使用数组索引。
答案 1 :(得分:3)
在此循环中:
for(int i = 0; i < rows * cols; i++) {
*result.data = *elements; //copy each element to Matrix instance
result.data++;
elements++;
}
您要在循环的每次迭代中更改result.data
指向的内容。循环结束时,它指向分配的数组的 end 。
随后打印数组时:
for(int i = 0; i < m.rows; i++) {
for(int j = 0; j < m.cols; j++) {
printf("%.0lf ", *m.data);
m.data++;
}
printf("\n");
}
您读取了数组的末尾,然后将m.data
移到了数组的末尾。这将调用undefined behavior。调用free
时,您进一步调用未定义的行为,因为m.data
不再指向malloc
返回的值。
您可以在两个地方都使用数组索引语法来解决此问题,而不用修改指针值。
在loadMatrix
中:
for(int i = 0; i < rows * cols; i++) {
result.data[i] = elements[i];
}
在printMatrix
中:
for(int i = 0; i < m.rows; i++) {
for(int j = 0; j < m.cols; j++) {
printf("%.0lf ", m.data[i*m.rows+j);
}
printf("\n");
}