A pointer to a pointer to a structure giving a headache.,

I'm not sure how to explain this, but this piece of code may compile fine, but when you run it, SIGSEV. Please, can someone tell me exactly where I was wrong? The fact is that I want to have access to elements by index, as shown below, and at the same time be able to work with the structure.

#include <stdio.h> #include <stdlib.h> /* 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; } 
+4
source share
5 answers

The problem is the insert method in the line of code you marked in the question

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

Nowhere in your program do you allocate memory for the p array inside the person structure. Therefore, this value will always be NULL . Attempting to assign this value rightfully will cause your program to crash.

To fix this, you need to make sure that the p array is large enough to place the index provided by the expression sample->id . The best way to achieve this is to use the realloc function and add a field in person to store the size of the p array

Here is a quick example. Note. Verification error and 0 memory initialization omitted for 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); } ... } 

It seems strange, although the name and age are always indexed through the sample->id field. This means that it always fits in the same place, in which case the array is not needed. Can you talk about how this should work?

+5
source

In your init () function, you set sample->p = NULL . In your insert () function, you are trying to dereference an element → p sample->p[sample->id]->name . Since you did not point → p to any repository, you cannot cast it.

0
source
 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 not initialized correctly. If you look at init , it is really initialized to NULL . sample->p[anything] therefore splits the null pointer by calling segfault.

0
source

When you call your init() function, you allocate memory for several person structures and set the pointer 'p' of the first structure to NULL.

Then you try to write the memory indicated by "p". Which, of course, is still NULL.

Given your comments, I don't think init () does what you want. It allocates space for an array of face structures, not a person with an array of "p". Also, why a double pointer?

Recheck your design :) I usually do this on a blackboard or pencil and paper, using boxes for my “objects” and arrows for my pointers. This will clarify your ideas and possibly show you the errors before they ever reach the code.

0
source
 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; } 

And now these two statements are valid -

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

Source: https://habr.com/ru/post/1344811/


All Articles