puntero a un puntero a una estructura que da dolor de cabeza. .

No estoy seguro de cómo explicar esto, pero este trozo de código puede comstackrse perfectamente pero cuando lo ejecutas, SIGSEV. Por favor, ¿alguien puede decir exactamente dónde me equivoqué? El hecho es que quiero poder acceder a los elementos por índice como se muestra a continuación y al mismo tiempo poder trabajar con la estructura.

#include  #include  /* This is a struct describing properties of an element */ struct element{ int age; char* name; }; /* This struct contains a pointer to a pointer on a element "struct element" */ struct person{ struct element** p; int id; }; /* Thus function initializes a struct person by allocation memory for it */ struct person* init(int size) { struct person* sample = (struct person* )malloc(size*sizeof(struct person)); sample->p = NULL; sample->id = 0; return sample; } /* use this function to insert a new element in the struct */ void insert(struct person* sample, char* _name, int _age) { sample->p[sample->id]->name = _name; /* the program crashes here according to the debugger , but why?? */ sample->p[sample->id]->age = _age; /* of course, this will cause trouble too because it has the same construct as the previous one */ sample->id++; } /* main entry */ int main() { struct person* student = init(10); /* Allocating space for 10 students */ insert(student, "kido", 8); printf("Your name is %s and your age is %d", student->p[0]->name, student->p[0]->age); /* we can't write student->p->name */ return 0; } 

El problema está en el método de insert en la línea de código que marcó en la pregunta

 sample->p[sample->id]->name = _name; 

En ninguna parte de su progtwig asigna memoria para la matriz p dentro de la estructura de la person . Por lo tanto, este valor siempre será NULL . El bash de asignar a este valor conducirá legítimamente a un locking de su progtwig.

Para solucionar este problema, debe asegurarse de que la matriz p sea ​​lo suficientemente grande como para acomodar el índice proporcionado por la expresión sample->id . La mejor manera de lograr esto es usar la función realloc y agregar un campo a la person para almacenar el tamaño de la matriz p

Aquí hay una muestra rápida. Nota: La comprobación de errores y la inicialización 0 de la memoria se omiten para bevity.

 struct person{ struct element** p; size_t length; int id; }; void insert(struct person* sample, char* _name, int _age) { if (sample->id >= sample->length) { sample->p = realloc(sample->p, sizeof(element*) * sample->id); } ... } 

Sin embargo, parece extraño que el nombre y la edad siempre se indexen a través del campo sample->id . Esto indica que siempre se coloca en la misma ubicación, en cuyo caso no se necesita una matriz. ¿Puedes explicar cómo funciona esto?

En tu función init () configuras sample->p = NULL . En su función insert () intenta eliminar la referencia al -> p miembro sample->p[sample->id]->name . Como no has señalado -> p a ningún almacenamiento, no puedes desreferirlo.

 Starting program: /home/nathan/c/seg Program received signal SIGSEGV, Segmentation fault. 0x0000000000400597 in insert (sample=0x601010, _name=0x400730 "kido", _age=8) at seg.c:28 28 sample->p[sample->id]->name = _name; /* the program craches here according to the debugger , but why?? */ (gdb) backtrace #0 0x0000000000400597 in insert (sample=0x601010, _name=0x400730 "kido", _age=8) at seg.c:28 #1 0x0000000000400601 in main () at seg.c:38 (gdb) p sample->id $1 = 0 (gdb) p sample->p $2 = (struct element **) 0x0 

sample->p no se está inicializando correctamente. Si miras en init , de hecho se inicializa a NULL . sample->p[anything] por lo tanto, anula las referencias de un puntero nulo, causando un fallo de seguridad

Cuando llama a su función init() , asigna memoria para un número de estructuras de person y establece el puntero ‘p’ de la primera estructura en NULL.

Luego intentas escribir la memoria apuntada por ‘p’. Que es, por supuesto, todavía nulo.

Dados tus comentarios, no creo que init () esté haciendo lo que quieres que haga. Es asignar espacio para una matriz de estructura de persona, en lugar de una persona con una matriz ‘p’. Además, ¿por qué el doble puntero?

Vuelva a revisar su diseño 🙂 Por lo general, lo hago en una pizarra, o lápiz y papel, usando cuadros para mis ‘objetos’ y flechas para mis punteros. Aclarará sus ideas y posiblemente le mostrará errores antes de que scopen el código.

 struct person* init(int size) { struct person* sample = (struct person* )malloc(size*sizeof(struct person)); sample->p = NULL; // p is a pointer to a pointer which is initialized to NULL // So, it cannot be dereferenced with out pointing to a valid // memory location. // sample -> p = (struct person**) malloc( sizeof(struct *person) ); // sample[p] = (struct(person*)) malloc( sizeof(struct person) ); // struct** -> struct* -> struct sample->id = 0; return sample; } 

Y ahora, estas dos afirmaciones son válidas.

 sample->p[sample->id]->name = _name; sample->p[sample->id]->age = _age;