Reputation: 105
I create a struct, pass the pointer of pointer into the function to then call malloc()
. That all works fine.
However if I try to access the memory, the program just freezes. If I call another function and change access the memory then everything works fine.
void test(TFeld *Feld, TEinstellung E)
{
int i;
for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
{
Feld[i].Schiff_Vorhanden = false;
Feld[i].Schiff_Versunken = false;
Feld[i].Ueberprueft = false;
}
}
void initField (TEinstellung E, TFeld **Feld)
{
int i;
*Feld = (TFeld*)malloc(E.Groesse_X*E.Groesse_Y*sizeof(TFeld));
test(*Feld,E);
/* for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
{
Feld[i]->Schiff_Versunken = (bool*)false;
// (*Feld[i]).Schiff_Versunken = false;
//Feld[i]->Ueberprueft = false;
} */
}
with the definiton of TFeld:
typedef struct TFeld
{
bool Schiff_Vorhanden = false;
bool Ueberprueft = false;
bool Schiff_Versunken = false;
} TFeld;
The part I commented out just crashed the program while using the test function works.
Can someone please explain me that behavior.
Upvotes: 2
Views: 183
Reputation: 73366
Whats the problem ?
In InitField()
the parameter Feld
is declared as a pointer to a pointer to TFeld.
*Feld
is hence a pointer to TFeld
. It is correctly initialized to a freshly allocated memory region of the correct size.
You then call test()
passing *Feld
as argument. Unfortunately you call the argument Feld
as well, so that the type of these variable is different and could cause some headaches. But this is not the problem. The test function should do what yo expect.
When you're back in InitField()
you then try to access to the elements that you have initialized:
Feld[i]->Schiff_Versunken = ... //ouch !!!
This takes the pointer to pointer and access the ith pointer in that table. But as your pointer of pointer is just a poitner and not an array, you get back a pointer which is completely corrupt. You then dereference this rogue pointer with ->
pretending that it points to a TFeld
. When you then assign a valu into this rogue address you have undefined behavior (could be segfault, could be freeze, could be anything).
Edit: additional information on pointer dereferencing:
The operators *
->
and []
have an order of precendence which you have to get used to. Let's look at the TFeld **Feld
:
*Feld[i]
is the same that *(Feld[i])
because first []
is applied and then only *
. By the way, going further, and applying pointer arithmetic rules, it's the same as *(*(Feld+i))
. In any case, it's not what yo want*Feld[i].xxx
is the same as *((Feld[i]).xxx)
because .
has a higher precedence than *
. This will not compile because Feld[i]
is not of type TFeld
Feld[i]->xxx
is the same as (Feld[i])->xxx
(because []
and ->
have the same precedence but when both appear they are applied from left to right). This is further the same as (*(Feld[i])).xxx
. And still not what you want.But lets visualize to understand the impact of applying dereferencing in a different order. On top is what you need. The botom is what you should avoid:
How to solve ?
I suggest to change the commented out part into:
for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
{
(*Feld)[i].Schiff_Versunken = false;
(*Feld)[i].Schiff_Versunken = false;
(*Feld)[i].Ueberprueft = false;
}
Or if you don't like stars and partenheses:
Feld[0][i].Schiff_Versunken = false;
Feld[0][i].Schiff_Versunken = false;
Feld[0][i].Ueberprueft = false;
DOuble indirections are allways a little tricky. Whenever you're in doubt, add some parentheses.
A final word: I assumed here that InitField()
was called with a valid pointer to a pointer to TFeld
, so that *Feld
would without a doubt point to a pointer to TFeld
. If this would be the case, the pointer of you memory allocation could be written anywhere in memory, causing again memory corruption. If in doubt, make an edit tou your question showing the calling code so that I can check.
Upvotes: 4
Reputation: 524
There is difference when you do it inside a function and directly . Because here Feld
is a pointer to structure in test()
, whereas it is a pointer to the pointer to the structure in initField()
.
When you used malloc(), the pointer to the structure got initialised, hence it didnt crashed when accessed inside test()
. But the pointer to the pointer is still uninitialized, hence caused the seg fault in initField()
.
So you have to allocate the double pointer correctly. Check this link for reference : C - dynamic memory allocation using double pointer
Upvotes: 0
Reputation: 1494
Feld
is a pointer to an array of structs. So you have to (1) dereference the pointer, then (2) index into the array, and finally (3) access the field inside the struct.
There are two ways to write this within your for
loop; which one you like better is a question of taste:
(*Feld)[i].Schiff_Versunken = false; // option 1
(*Feld + i)->Schiff_Versunken = false; // option 2
Upvotes: 1