2013-07-17 6 views
0

Это проблема, связанная с изучением C hardway. Это система управления базами данных в C У меня есть три структуры: -Инициализация вложенной структуры

struct Address { 
     int id; 
     int set; 
     char *name; 
     char *email; 
}; 

struct Database { 
int rows; 
    struct Address *row; 
}; 

struct Connection { 
    FILE *file; 
    struct Database *db; 
}; 

Я пытаюсь инициализировать структуру базы данных. Однако я получаю segfault

void Database_create(struct Connection *conn, int no_of_rows) 
    { 
     int i = 0; 
    conn->db->row_num = no_of_rows; 

     for(i = 0; i < conn->db->row_num; i++) { 

     // make a prototype to initialize it 
     struct Address addr; 
     addr.id = i; 
     addr.set = 0; 

     // then just assign it 
     conn->db->rows[i] = addr; 
     } 
    } 

Я сделал еще одну функцию, которая выделяет память этим структурам.

 struct Connection *Database_open(const char *filename, char mode) 
     { 
     struct Connection *conn = malloc(sizeof(struct Connection)); 
     if(!conn) die("Memory error"); 

    int number = conn->db->rows; 

     conn->db = malloc(sizeof(struct Database)); 
    if(!conn->db) die("Memory error"); 

     conn->db->row = malloc(sizeof(*conn->db->row) * number); 
     if(!conn->db->row) die("Memory error"); 

     if(mode == 'c') { 
     conn->file = fopen(filename, "w"); 
     } else { 
     conn->file = fopen(filename, "r+"); 

     if(conn->file) { 
     Database_load(conn); 
     } 
    } 

    if(!conn->file) die("Failed to open the file"); 

     return conn; 
    } 

Valgrind говорит: «Использование неинициализированного значения размера 4» в Database_open()

Можно ли предположить, что я могу делать неправильно здесь?

+0

Почему вы используете 'rows' в качестве массива, когда это просто' int'? – tay10r

+0

Используйте отладчик, чтобы узнать, что вызывает segfault. Скорее всего, 'conn-> db' не инициализирован или что-то –

+0

@Ajit вы должны указать, как вы вызываете' Database_create' – tay10r

ответ

1

db в Connection и row в Database являются неинициализированными указателями. Вам необходимо инициализировать их и предоставить хранилище для структур, на которые они указывают.

Вы, вероятно, может сэкономить динамическое распределение путем изменения Connection иметь его Database в качестве члена, а не указатель

struct Connection { 
    FILE *file; 
    struct Database db; 
}; 

Вам нужно выделить память для строк базы данных

conn->db.row = malloc(no_of_rows * sizeof(*conn->db.row)); 

Database_create бы затем посмотрите примерно на

int Database_create(struct Connection *conn, int no_of_rows) 
{ 
    int i = 0; 
    conn->db.rows = no_of_rows; 
    conn->db.row = malloc(no_of_rows * sizeof(*conn->db.row)); 
    if (conn->db.row == NULL) { 
     /* out of memory */ 
     return 1; /* indicate failure to caller */ 
    } 
    for(i = 0; i < conn->db->rows; i++) { 
     conn->db.row[i].id = i; 
     conn->db.row[i].set = 0; 
    } 
    return 0; /* indicate success to caller */ 
} 

Обратите внимание, что предполагается, что память уже выделена для Connection

+1

Если я не читаю что-то не так, 'rows' является int, а не указателем – tay10r

+0

Спасибо, я имел в виду' row' ('Address *'). Теперь исправлено – simonc

+0

, вы также можете указать, что он также использует 'rows' в качестве указателя в своем коде – tay10r

Смежные вопросы