Say you have these 2 funcs, like you posted:
void func2(float** floats) {
*floats[1] = 1.0;
}
void func(float** floats) {
func2(floats);
}
Then you have the following code:
float* floats;
func(&floats);
What happens? First, floats
is a float *
, and since it's not assigned, it points to a random memory location, say 0xBADD
. If you write to here, you're liable to screw something up.
The address of floats
, &floats
is another memory location pointing to where it is on the stack, say 0x1000
. This is passed to func
, which is then verbatim passed to func2
.
What does func2
do? It tries to write something in the location *floats[1]
. I'm not sure what happens first, the bracket or the star, so let's take both cases:
*(floats[1])
: First you find what floats[1]
is. Since floats
is the memory location of the initial floats
variable, this is 0x1000
. floats[1]
would be 0x1004
, since pointers are 4 bytes wide assuming a 32-bit system. Then you try to dereference this pointer, which is the value of whatever is in memory location 0x1004
. This could be anything, like 0xBAD2
, so trying to write a float value there most likely causes a segfault.
(*floats)[1]
. Here you first dereference floats
, which gets you 0xBADD
, of type float *
. You then try to write a value into 0xBADD + 4
, or 0xBAE1
. This is memory that hasn't been allocated for you, so writing there will likely cause a segfault.
Either way, you're messing with memory that isn't yours, thus leading to a segfault.