Search code examples
cstructcalloc

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.

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("%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). Directly callocing the array to the struct pointers doesn't affect the result. Mallocing, callocing, not typecasting, all no effect.

Thanks to Xcode and gdb I can also see that at the point of the segfault. The structure pointers do NOT seem to point to the arrays


Solution

  • I suggest you run your code under 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. Check that the values you get out are what you expect.