Reputation: 3616
I have a struct Node
and Box
given by
typedef struct Node{
Particle p;
Box box;
struct Node *son[4];
}Node
and
typedef struct Box{
double low[3];
double up[3];
}Box
I have two functions insert()
and sonumb()
where I want to use these structures.
void insert(Particle *p, Node *t){
Box sonbox;
int b=sonumb(&t->box, &sonbox, p);
t->son[b]->box = sonbox; // <--- Produces Segmentation fault (core dumped)
}
int sonumb(Box *box, Box *sonbox, Particle *p){
int b=0;
for(int d=0;d<3;d++){
sonbox->up[d] = 0.5*box->up[d];
sonbox->low[d] = 0.5*box->low[d];
}
b=1; // b=[0,3] just for this example
}
sonum()
returns an integer value b
. sonbox
represents after the call of sonumb()
a smaller box inside of t->box
. I return the right values for sonbox
after the call. So sonbox
is not empty. But if I want to copy those values like t->son[b]->box = sonbox
I get an segmentatioin fault. What did I miss?
Upvotes: 0
Views: 74
Reputation: 726479
You have nearly certainly missed the allocation of son
elements. In order for the expression t->son[b]->box
to produce a valid target of an assignment, t->son[b]
needs to be assigned a pointer to a valid Node
structure. The pointer needs to point to some Node
that you have previously allocated.
If child nodes are shared among nodes, this should be a malloc
-ed node. This adds quite a bit of complexity, because deleting shared nodes is non-trivial. Two common approaches to working with shared nodes are to (1) allocate all nodes at once in a large array, and use them one-by-one as they become needed, and (2) add reference count to the struct
, increment it when taking a pointer, and decrement it when the reference is no longer needed. The second approach is extremely difficult to implement; see if you can avoid it before committing to it.
On the other hand, if child nodes are owned exclusively by their parent, you have a very simple solution: allocate Node
with malloc
before the assignment of son[b]
elements, and free
them when you are done with the node:
Box sonbox;
int b=sonumb(&t->box, &sonbox, p);
t->son[b] = calloc(1, sizeof(Node)); // Allocate the node
t->son[b]->box = sonbox;
Use of calloc
ensures that the memory of the Node
is cleared prior to making other assignments. If this is not necessary, because you assign all members in the rest of your function, replace the call with malloc
:
t->son[b] = malloc(sizeof(Node));
Upvotes: 1
Reputation: 3063
adding to @dasblinkenlight's comment.
Box sonbox; ---> This variable is on stack
int b=sonumb(&t->box, &sonbox, p); --> content of t->box is COPIED to sonbox, not by reference but by value.
t->son[b]->box = sonbox; // --> Assigning stack variable is incorrect, because it will vanish once you exit function. OR as @dasblinkenlight suggested pass the value but not the pointer.
Upvotes: 0