3

次のコードがありますが、セグメンテーション違反が発生する理由について少し混乱しています。

typedef struct {
  int tag;
  int valid;
} Row;

typedef struct {
  int index;
  int num_rows;
  Row **rows;
} Set;

/* STRUCT CONSTRUCTORS */

// Returns a pointer to a new Sow.
// all fields of this row are NULL
Row* new_row() {
  Row* r = malloc(sizeof(Row));
  return r;
}

// Returns a pointer to a new Set.
// the set's index is the given index, and it has an array of
// rows of the given length.
Set* new_set( int index, int num_rows, int block_size ) {
  Set* s = malloc(sizeof(Set));
  s->index = index;
  s->num_rows = num_rows;

  Row* rows[num_rows];
  for (int i = 0; i < num_rows; i++) {
    Row* row_p = new_row();
    rows[i] = row_p;
  }
  s->rows = rows;

  return s;
}

/* PRINTING */

void print_row( Row* row ) {
  printf("<<T: %d, V: %d>>", row->tag, row->valid);
}

void print_set( Set* set ) {
  printf("[ INDEX %d :", set->index);


  for (int i = 0; i < set->num_rows; i++) {
    Row* row_p = set->rows[i];
    print_row(row_p);
  }

  printf(" ]\n");
}


int main(int argc, char const *argv[]) {

  Set* s = new_set(1, 4, 8);
  print_set(s);


  return 0;

}

基本的に、 aSetは s の配列へのポインターを持ちますRowRow* row_p = set->rows[i];セットから行を取得する正しい方法だと思いますが、何かが足りないに違いありません。

4

2 に答える 2

4

Row*のローカル配列を割り当てています

  Row* rows[num_rows];
  for (int i = 0; i < num_rows; i++) {
    Row* row_p = new_row();
    rows[i] = row_p;
  }
  s->rows = rows;

そして、それを指し示すrowsポインタを置きます。Set関数が返された後、ローカル配列はもう存在しないためs->rows、ダングリング ポインターになります。関数が返された後も有効なメモリは、malloc(またはその従兄弟の 1 つ) に割り当てる必要があります。

于 2012-11-26T20:34:19.207 に答える
1

s->rowsrowsには、関数内のローカル変数のアドレスが割り当てられます。これは、戻り時にダングリング ポインターnew_set()であることを意味します。の配列を動的に割り当てて修正します。s->rowsnew_set()Row*

s->rows = malloc(num_rows * sizeof(Row*));
if (s->rows)
{
    /* for loop as is. */
}

s->rowsとその要素はfree()dでなければならないことに注意してください。

于 2012-11-26T20:34:10.000 に答える