0

This is a problem from learn C the hardway. This is database management system in C I have three structures :-

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

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

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

I trying to initialize the database structure. However I am getting a 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;
      }
  }

I've made another function which allocates memory to these structures.

     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 says "Use of uninitialized value of size 4" in Database_open()

Could anyone suggest what I might be doing wrong here?

5
  • why are you using rows as an array, when it is just an int? Commented Jul 17, 2013 at 16:39
  • Use a debugger to see what's causing the segfault. Most likely conn->db isn't initialized or something Commented Jul 17, 2013 at 16:39
  • @Ajit you should include how you are calling Database_create Commented Jul 17, 2013 at 16:46
  • rows is the number of tuples of the table . I am passing it as an argument at main when I create the database. Commented Jul 17, 2013 at 16:52
  • The line int number = conn->db->rows; dereferences conn->db before it is accessed. Presumably this is what valgrind is reporting. Commented Jul 17, 2013 at 19:35

1 Answer 1

1

db in Connection and row in Database are uninitialised pointers. You need to initialise them and provide storage for the structs they point to.

You can probably save some dynamic allocation by changing Connection to have its Database as a member rather than a pointer

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

You need to allocate memory for the database rows

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

Database_create would then look something like

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 */
}

Note that this assumes memory is already allocated for the Connection

Sign up to request clarification or add additional context in comments.

3 Comments

unless I'm reading something wrong, rows is an int and not a pointer
sure, you may also want to include that he is using rows as a pointer in his code as well
I've made another function which allocates memory to these structures.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.