Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Struct with pointer to array

Tags:

c

pointers

I have the following code, and I'm a bit confused as to why I'm getting a segmentation fault.

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;

}

Basically a Set has a pointer to a array of Rows. I'd think Row* row_p = set->rows[i]; would be the right way to get the row from a set, but I must be missing something.

like image 740
Nathan Lilienthal Avatar asked Jul 17 '26 03:07

Nathan Lilienthal


2 Answers

You are allocating a local array of Row*s

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

and let the rows pointer of the Set point to that. The local array doesn't exist anymore after the function returned, so s->rows is then a dangling pointer. Memory that shall still be valid after the function returned must be allocated with malloc (or one of its cousins).

like image 183
Daniel Fischer Avatar answered Jul 18 '26 21:07

Daniel Fischer


s->rows is assigned the address of the local variable rows in the function new_set(), which means s->rows is a dangling pointer when new_set() returns. Dynamically allocate an array of Row* to correct:

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

Remember that s->rows, as well as its elements, must be free()d.

like image 43
hmjd Avatar answered Jul 18 '26 19:07

hmjd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!