Reputation: 864
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 Row
s. 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.
Upvotes: 3
Views: 6954
Reputation: 183888
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).
Upvotes: 4
Reputation: 121971
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.
Upvotes: 1