struct matrix {
int m, n; // m rows, n columns
int** data;
char name[64];
};
struct matrix* alloc_matrix(const char* name, int m, int n) {
struct matrix *mat = malloc(sizeof(struct matrix));
strcpy(mat->name, name);
mat->m = m;
mat->n = n;
mat->data = (int**)malloc(sizeof(m) * (m * n));
return mat;
}
int main() {
struct matrix* mat1 = alloc_matrix("mat1", 4, 4);
mat1->data[0][0] = 2; <------------------------------ This line causes the error
return EXIT_SUCCESS;
}
所以我想实现矩阵。我定义了一个结构矩阵,它保存 matix 的名称、行数、列数和数据。使用函数alloc_matrix我想为结构对象分配内存。但是这个函数出了点问题,因为如果我想在分配的对象上检索或设置数据,我会收到运行时内存错误。
我希望有人在动态数据分配方面有更多经验并看到问题所在。
数据被用作二维数组。也就是说,它是一个数组,其中数组的每个元素本身都是一个整数数组。
mat->data = (int**)malloc(sizeof(m) * (m * n));
此行分配第一个数组。它现在有足够的空间来容纳 m*n 指针,但指针不指向任何内容。这不是你想要的。
你想要的是数据包含 m 个指针,每个指针包含 n 个元素。
mat->data = (int**)malloc(sizeof(*mat->data) * m);
if(!mat->data)
{
//handle error case
}
for(int ii = 0; ii < m; ++ii)
{
mat->data[ii] = (int*)malloc(sizeof(**mat->data) * n);#
if(!mat->data[ii])
{
//handle error case
}
}
mat->data = (int**)malloc(sizeof(m) * (m * n));
此行不会按照您的想法执行。您需要首先为指针分配空间,然后为所有已分配指针的引用对象分配空间。
重要!!!您需要始终检查malloc的结果!
它必须是:
if(mat->data = malloc(sizeof(*mat->data) * (m)))
{
for(size_t index = 0; index < n; index++)
{
if(!(mat->data[index] = malloc(sizeof(**mat->data) * n)))
{
//do something if malloc failed
}
}
}
https://godbolt.org/z/skBJzb
就个人而言,在这种情况下,我不会这样做。我个人更喜欢限制 malloc 的数量
struct matrix {
size_t r, c; // r rows, c columns
char name[64];
int data[];
};
struct matrix* alloc_matrix(const char* name, size_t rows, size_t cols) {
struct matrix *mat = malloc(sizeof(*mat) + rows * cols * sizeof(mat -> data[0]));
if(mat)
{
strcpy(mat->name, name);
mat->r = rows;
mat->c = cols;
}
return mat;
}
int setdata(struct matrix *mat, size_t row, size_t col, int val)
{
int result = -1;
if(mat)
{
if(row < mat -> r && col < mat -> c)
{
mat -> data[row * mat -> c + col] = val;
result = 0;
}
}
return result;
}
int main() {
struct matrix* mat1 = alloc_matrix("mat1", 4, 4);
if(mat1)
{
printf("set result %dn", setdata(mat1, 2, 2, 0));
printf("set result %dn", setdata(mat1, 5, 2, 0));
}
}