Скажем, у вас есть эти 2 функции, которые вы опубликовали:
void func2(float** floats) {
*floats[1] = 1.0;
}
void func(float** floats) {
func2(floats);
}
Тогда у вас есть следующий код:
float* floats;
func(&floats);
Что происходит? Во-первых, floats
- это float *
, и, поскольку он не назначен, он указывает на случайную ячейку памяти, скажем, 0xBADD
. Если вы напишите сюда, вы наверняка что-то напортачите.
Адрес floats
, &floats
- это еще одна ячейка памяти, указывающая, где она находится в стеке, скажем, 0x1000
. Это передается в func
, который затем дословно передается в func2
.
Что делает func2
? Он пытается что-то написать в локации *floats[1]
. Я не уверен, что произойдет сначала, скобка или звезда, поэтому давайте рассмотрим оба случая:
*(floats[1])
: Сначала вы обнаружите, что такое floats[1]
. Поскольку floats
- это ячейка памяти исходной переменной floats
, это 0x1000
. floats[1]
будет 0x1004
, так как указатели имеют ширину 4 байта при условии 32-битной системы. Затем вы пытаетесь разыменовать этот указатель, который является значением того, что находится в ячейке памяти 0x1004
. Это может быть что угодно, например, 0xBAD2
, поэтому попытка записать значение с плавающей запятой, скорее всего, приведет к segfault.
(*floats)[1]
. Вот вам первая разыменование floats
, которое дает вам 0xBADD
, типа float *
. Затем вы пытаетесь записать значение в 0xBADD + 4
или 0xBAE1
. Это память, которая не была выделена для вас, поэтому запись в нее, скорее всего, приведет к segfault.
В любом случае, вы возитесь с памятью, которая не принадлежит вам, что приводит к segfault.