sirven que punteros puntero para operaciones los declaracion con cadenas aritmetica c file pointers segmentation-fault structure

que - puntero a una estructura en otra, escribir y leer desde el archivo da SegFault



punteros c++ (2)

Estoy mejorando mis habilidades C de Learn C The Hard Way, actualmente estoy en el 17mo ejercicio .

Estoy haciendo la parte de ''Créditos adicionales''. Haciendo que el código de la base de datos dado en esa página sea obtenido, estoy tratando de

"Cambie el código para aceptar parámetros para MAX_DATA y MAX_ROWS, guárdelos en la estructura de la base de datos y escríbalos en el archivo, creando así una base de datos que pueda ser arbitrariamente dimensionada"

Por lo tanto, comenté las directivas #define y cambié las estructuras de direcciones y bases de datos tal como aparecen:

struct Address { int id; int set; char *name; char *email; }; struct Database { int MAX_DATA; int MAX_ROWS; struct Address *rows; };

Entonces, puedo obtener los parámetros MAX_DATA y MAX_ROWS del usuario para crear una base de datos según su gusto. Otras cosas que cambié en el código son:

La función Database_create:

void Database_create(struct Connection *conn, int MAX_DATA, int MAX_ROWS) { int i = 0; conn->db->MAX_DATA = MAX_DATA; conn->db->MAX_ROWS = MAX_ROWS; conn->db->rows = malloc(sizeof(struct Address) * MAX_ROWS); for(i = 0; i < MAX_ROWS; i++) { struct Address addr = {.id = i, .set = 0}; conn->db->rows[i] = addr; } }

La parte donde obtengo ''Invalid read of 4 bytes'', y SegFault es:

void Database_set(struct Connection *conn, int id, const char *name, const char *email) { struct Address *addr = &conn->db->rows[id]; int MAX_DATA = conn->db->MAX_DATA; if(addr->set) die("Already set, delete it first"); /* This if statement gives error for addr->set */ addr->set = 1; addr->name = malloc(sizeof(char) * MAX_DATA); addr->email = malloc(sizeof(char) * MAX_DATA); // WARNING: bug, read the "How To Break It" and fix this char *res = strncpy(addr->name, name, MAX_DATA); // demonstrate the strncpy bug if(!res) die("Name copy failed"); res = strncpy(addr->email, email, MAX_DATA); if(!res) die("Email copy failed"); }

Sé que este fragmento de código no es la parte completa, pero no puedo pegar todo el código aquí. Por lo tanto, lo publiqué aquí: http://pastebin.com/EbKShT3r. Puedo crear y escribir la base de datos para la primera ejecución usando la opción ''c''. Sin embargo, para agregar entradas usando la opción ''s'', se produce la falla de segmentación.

EDITAR : Entonces, finalmente, obtuve este programa trabajando con la solución dada por @WhizCraig Sin embargo, para liberar la memoria, esto es lo que estoy intentando:

void Database_close(struct Connection *conn) { int i; if (conn) { int MAX_ROWS = conn->db->MAX_ROWS; for (i=0; i<MAX_ROWS; i++) { struct Address *row = conn->db->rows+i; if (row->set) { free(row->name); free(row->email); } } free(conn->db->rows); if(conn->file) fclose(conn->file); if(conn->db) free(conn->db); free(conn); } }

Y, estoy recibiendo errores en Valgrind, la memoria está goteando. No entiendo el error en el código anterior. Sin embargo, el problema principal parece estar resuelto :)


Modifiqué el código Rohit publicado aquí: http://pastebin.com/MvLXkDCz para arreglar las pérdidas de memoria. Corre a través de Valgrind sin ningún error. Las modificaciones relevantes se publican a continuación:

void Database_close(Connection *conn) { size_t i; if(conn) { if(conn->db && conn->db->rows) { for(i = 0; i < conn->db->max_rows; i++) { Address *cur = conn->db->rows[i]; free(cur->name); free(cur->email); free(cur); } free(conn->db->rows); } if(conn->file) fclose(conn->file); if(conn->db) free(conn->db); free(conn); } } void Database_delete(Connection *conn, int id) { conn->db->rows[id]->set = 0; }

Puede encontrar el programa completo aquí: https://github.com/sookoor/Learn-C-the-Hard-Way/blob/master/ex17.c


struct Address { int id; int set; char *name; char *email; }; struct Database { int MAX_DATA; int MAX_ROWS; Address **rows; // USE ARRAY OF POINTERS }; void Database_create(Connection *conn, int MAX_DATA, int MAX_ROWS) { int i = 0; conn->db->MAX_DATA = MAX_DATA; conn->db->MAX_ROWS = MAX_ROWS; conn->db->rows = (Address**)malloc(sizeof(Address*) * MAX_ROWS); for(i = 0; i < MAX_ROWS; i++) { conn->db->rows[i] = (Address*)malloc(sizeof(Address)); conn->db->rows[i]->id = i; conn->db->rows[i]->set = 0; } } void Database_set(Connection *conn, int id, const char *name, const char *email) { if (!(conn && conn->db && conn->db->rows && conn->db->rows[id])) return; Address *addr = conn->db->rows[id]; int MAX_DATA = conn->db->MAX_DATA; if(addr->set == 0) die("Already set, delete it first"); addr->set = 1; addr->name = malloc(sizeof(char) * MAX_DATA); addr->email = malloc(sizeof(char) * MAX_DATA); char *res = strncpy(addr->name, name, MAX_DATA); if(!res) die("Name copy failed"); res = strncpy(addr->email, email, MAX_DATA); if(!res) die("Email copy failed"); } void Database_close(Connection *conn) { size_t i; if(conn) { if (con->db && conn->db->rows) { for (i = 0; i < conn->db->MAX_ROWS; i++) { Address *cur = conn->db->rows[i]; free(cur); } } if(conn->file) fclose(conn->file); if(conn->db) free(conn->db); free(conn); } }