2012-01-25 4 views
0

Cで疎行列の割り当てを完了しようとしています。値と座標のリストとして保持されている疎行列をYale形式に変換しています。構造体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-を交換する場合> Aで満たされていますA printfで、それは正常に動作します)。 配列をstructポインタに直接呼び出しても結果には影響しません。 Mallocingは、型キャストではなく、すべての効果がありません。

Xcodeとgdbのおかげで、私はsegfaultの時点でもそれを見ることができます。

#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:構造ポインタが

+0

タイプと変数の両方に同じ名前を付けるのは良い考えではありません。他の人(または数週間であなた自身)に混乱を招く可能性があるためです。 –

+0

最初のループの最後に 'i'と' j'の値を表示して、 'A' /' IA'/'JA'に割り当てられたメモリの最後を過ぎていないことを確認してください。 – NPE

+1

コンパイル可能なフラグメントを投稿した場合に役立ちます。また、を含め、キャストを削除します。個人的には、typedefも削除し、すべてのintをunsigned intで置き換えることになりますが、それは好みの問題です。 – wildplasser

答えて

0

Valgrindの下でコードを実行することをお勧めします。これは、バッファオーバーフローエラーを報告するはずです。 (バッファオーバーフローは、配列の最後を過ぎて書き込む場所です)。

コードの単体テストを書くことをお勧めします。それらは非常に有用なバグを検出することができます。特に、すべての位置に値を持つ3x3入力行列を使ってテストを書くことをお勧めします。出て行く値が期待どおりであることを確認してください。

0

はそれがコンパイルされ得るために配列を指すようには見えませんが、私はスニペットにこれを前に付加する必要がある、私はより読みやすい何か(私見にプログラムを変換しました)。私は、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){}条件を移動して、1文字のインデックスを2文字の同等のものに置き換えました。また、すべてのインデックスは署名されていません(そうする必要があります)

関連する問題