2012-11-26 5 views
3

J'ai le code suivant, et je suis un peu confus quant aux raisons pour lesquelles je reçois un défaut de segmentation.C Struct avec pointeur sur le tableau

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; 

} 

Fondamentalement, un Set a un pointeur vers un tableau de s. Je pense que Row* row_p = set->rows[i]; serait le bon moyen d'obtenir la ligne d'un ensemble, mais je dois manquer quelque chose.

Répondre

4

Vous allouent un tableau local de 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; 

et laissez le pointeur rows du point Set à cela. Le tableau local n'existe plus après la fonction retournée, donc s->rows est alors un pointeur qui pend. La mémoire qui doit encore être valide après la fonction renvoyée doit être affectée avec malloc (ou l'un de ses cousins).

1

s->rows est attribuée l'adresse de la variable locale dans la fonction rowsnew_set(), ce qui signifie s->rows est un dangling pointer lorsque new_set() rendements. Dynamiquement allouer un tableau de Row* corriger:

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

Rappelez-vous que s->rows, ainsi que ses éléments, doit être free() d.