2012-01-25 68 views
0

我正在嘗試完成C中稀疏矩陣的賦值。我有一個稀疏矩陣作爲值和座標列表保存,並將其轉換爲耶魯格式。結構calloc中的動態數組或指針失敗,C

我遇到了一個似乎沒有人見過的奇怪的內存分配問題。我的代碼是:

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; 
} 

這裏是耶魯大學的結構:

typedef struct y{ 
int n; 
int m; 
int elements; 
int *IA; 
int *JA; 
int *A; 
} yale; 

但在環路上的第一次迭代的第一個相關的printf的程序段錯誤。

 printf("%d,",yale->A[i]); 

我敢肯定: matrix_elements是(在我的測試案例9)的整數 matrix_rows是一個整數 A/IA/JA都充滿了正確的值(如果換成yale->一種在printf中,它工作正常)。 將數組直接調用到結構指針不會影響結果。編程,調用,不是類型轉換,都不起作用。

感謝Xcode和gdb我也可以看到,在段錯誤點。該結構的指針就似乎指向數組

+0

對於一個類型和一個變量都有相同的名字不是一個好主意,因爲它可能會導致其他人(或者幾個星期後)的混淆。 –

+0

在第一個循環結束時打印出'i'和'j'的值,以確保你沒有超過分配給'A' /'IA' /'JA'的內存末尾。 – NPE

+1

如果您發佈了可編譯的片段,這將有所幫助。另外:包括並移除鑄件。就我個人而言,我也會刪除typedef,並用unsigned int替換所有的int,但這是一個有趣的問題。 – wildplasser

回答

0

我建議你在Valgrind下運行你的代碼。這應報告緩衝區溢出錯誤。 (緩衝區溢出是您在數組末尾寫入的地方)。

我也建議你爲你的代碼編寫一些單元測試。他們可以非常有用地檢測錯誤。特別是,我建議你寫一個3x3輸入矩陣的測試,在每個位置都有一個值。檢查你獲得的數值是否符合你的期望。

0

要得到它的編譯,我需要預先設置此的片段:

#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; 

更新:我改變了計劃到更多的東西可讀(恕我直言)。我不知道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; 
} 

注意:我將(ii == 0){}條件移出循環,並用兩個字母的等價替換爲單字母索引。此外:所有的指數是無符號的(因爲他們應該是)