[英]Dynamic array in struct calloc or pointers failing, C
I'm attempting to complete an assignment on sparse matrices in C. I have a sparse matrix held as a list of values and coordinates and am converting it to Yale format. 我试图在C中完成对稀疏矩阵的赋值。我将稀疏矩阵保存为值和坐标的列表,并将其转换为Yale格式。
I have run into a strange memory allocation issue that no one seems to have seen before. 我遇到了一个奇怪的内存分配问题,以前似乎没人见过。 My code is: 我的代码是:
yale* convertMatrix(matrix_list* input){
int matrix_elements = input->elements;
int matrix_rows = input->m;
yale* yale = (struct y*)calloc(1, sizeof(yale));
int* A = (int*)calloc(matrix_elements, sizeof(int));
int* IA = (int*)calloc(matrix_rows + 1, sizeof(int));
int* JA = (int*)calloc(matrix_elements, sizeof(int));
printf("%d elements\n",matrix_elements);
yale->A = A; // Value
yale->IA = IA; // Row (X)
yale->JA = JA; // Column (Y)
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
list* tmp_list = input->first;
for(int i = 0, j = 0, tmp_y = 0; i < matrix_elements && tmp_list!=NULL; i++){
printf("Input Value: %d \n",tmp_list->point.value);
A[i] = tmp_list->point.value;
// Initialise the first row
if(i == 0) IA[0] = tmp_list->point.x;
else{
// Add a new row index
if(tmp_y != tmp_list->point.x){
j++;
IA[j] = i;
tmp_y = tmp_list->point.x;
}
}
JA[i] = tmp_list->point.y;
tmp_list = tmp_list->next;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%d,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->JA[i]);
return yale;
}
And here is the struct for yale: 这是耶鲁的结构:
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
But the program segfaults at the first relevant printf on the first iteration of the loop. 但是程序在循环的第一次迭代时在第一个相关的printf处出现段错误。
printf("%d,",yale->A[i]);
I'm positive: matrix_elements is an integer (9 in my test case) matrix_rows is an integer A / IA / JA are all filled with correct values (if you swap yale->A for A in the printf, it works fine). 我很肯定:matrix_elements是一个整数(在我的测试用例中为9)matrix_rows是一个整数A / IA / JA都填充有正确的值(如果在printf中将yale-> A换为A,则可以正常工作)。 Directly callocing the array to the struct pointers doesn't affect the result. 将数组直接调用到结构指针不会影响结果。 Mallocing, callocing, not typecasting, all no effect. Mallocing,callocing,而不是typecasting都无效。
Thanks to Xcode and gdb I can also see that at the point of the segfault. 感谢Xcode和gdb,我也可以在segfault的时候看到它。 The structure pointers do NOT seem to point to the arrays 该结构的指针似乎并不指向数组
To get it compiled, I need to prepend this to the snippet: 要对其进行编译,我需要在代码段之前添加它:
#include <stdlib.h>
#include <stdio.h>
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
typedef struct list {
struct list *next;
struct point { int x,y,value; } point;
} list;
typedef struct matrix_list {
int elements;
int m;
int n;
struct list *first;
int *point;
} matrix_list;
UPDATE: I transformed the program into something more readable (IMHO). 更新:我将该程序转换为更具可读性(IMHO)。 I don't have the faintest idea what the IA and JA are supposed to do, but the below fragment should be equivalent to the OP. 我不知道IA和JA应该做什么,但是下面的片段应该等同于OP。
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
struct y {
unsigned int n;
unsigned int m;
unsigned int elements;
unsigned int *IA;
unsigned int *JA;
int *A;
} ;
struct list {
struct list *next;
struct point { unsigned int x,y; int value; } point;
} ;
struct matrix_list {
unsigned int elements;
unsigned int m;
unsigned int n;
struct list *first;
} ;
struct y *convertMatrix(struct matrix_list* input)
{
unsigned int matrix_elements = input->elements;
unsigned int matrix_rows = input->m;
unsigned int ii,jj,tmp_y;
struct y *yale ;
struct list *tmp_list ;
yale = calloc(1, sizeof *yale);
assert (yale != NULL);
printf("%u elements\n",matrix_elements);
yale->A = calloc(matrix_elements, sizeof *yale->A);
assert (yale->A != NULL);
yale->IA = calloc(matrix_rows + 1, sizeof *yale->IA);
assert (yale->IA != NULL);
yale->JA = calloc(matrix_elements, sizeof *yale->JA);
assert (yale->JA != NULL);
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
// Initialise the first row, set start condition
// FIXME: this ignores the empty list or size=0 cases
yale->IA[0] = tmp_y = input->first->point.x;
ii = jj = 0;
for(tmp_list = input->first ;tmp_list; tmp_list = tmp_list->next) {
printf("Input Value: %d \n",tmp_list->point.value);
yale->A[ii] = tmp_list->point.value;
// Add a new row index
if(tmp_y != tmp_list->point.x){
jj++;
yale->IA[jj] = ii;
tmp_y = tmp_list->point.x;
}
yale->JA[ii] = tmp_list->point.y;
if (++ii >= matrix_elements ) break;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%u,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%u,",yale->JA[i]);
return yale;
}
Note: I moved the (ii == 0) {} condition out of the loop, and replaced the one-letter indices by there two-letter equivalents. 注意:我将(ii == 0){}条件移出了循环,并用等效的两个字母替换了一个字母的索引。 Also: all the indices are unsigned (as they should be) 另外:所有索引都是无符号的(应该是无符号的)
I suggest you run your code under Valgrind . 我建议您在Valgrind下运行代码。 This should report the buffer overflow error. 这应该报告缓冲区溢出错误。 (A buffer overflow is where you write past the end of an array). (缓冲区溢出是您在数组末尾写的地方)。
I also recommend you write some unit tests for your code. 我还建议您为代码编写一些单元测试。 They can be very helpful detecting bugs. 它们对检测错误很有帮助。 In particular, I suggest you write a test with a 3x3 input matrix with a value in every position. 特别是,我建议您编写一个3x3输入矩阵的测试,每个位置都有一个值。 Check that the values you get out are what you expect. 检查得出的值是否符合您的期望。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.