Чтение неинициализированной переменной, которая имеет хорошее значение

Я столкнулся с этой ошибкой в ​​каком-то коде, работающем на процессоре Blackfin 533.

Первый раз Func() работает, fooStruct будет содержать мусор, но в следующей итерации старое значение, которое было возвращено getFoo() случайно все еще будет в fooStruct.foo,

FooStruct
{
double foo;
double bar;
};

void Func()
{
FooStruct fooStruct;

double bar = 123.4 / fooStruct.foo;

fooStruct.foo = getFoo();
fooStruct.bar = bar;
}

Это означает, что при первом запуске мы читаем из неинициализированной переменной, поведение которой не определено. Как насчет следующих итераций? Это все еще неопределенное поведение? Какое поведение мы можем ожидать при чтении неинициализированных переменных на встроенных процессорах?

1

Решение

Обнаружено одно неопределенное поведение, поведение которого и все последующие заявления тоже не определено.

Как это ни парадоксально, поведение любых заявлений до неопределенного тоже не определены.

Для Сортировать поведения, просить классифицировать неопределенное поведение не логично.

7

Другие решения

Да, это не определено, но поведение, которое вы наблюдаете, не обязательно удивительно; просто стек используется повторно, а повторно использованное пространство не инициализируется, и вы случайно использовали точно такое же расположение стека, что и при предыдущем вызове. Вся память должна содержать что-то, и если вы вызовете эту функцию, и случится повторное использование того же стекового фрейма, что и при предыдущем вызове, она будет содержать все, что там оставалось последним.

Например, если вы звоните:

Func() ;
Func() :

Это не определено, но не лишено смысла для второго звонка fooStruct.foo содержать значение, оставленное первым вызовом, потому что это то, что произойдет, когда компилятор бездействие инициализировать переменную.

Однако, если вместо этого у вас было:

void Func2()
{
int x = 0 ;
int y = 0 ;
Func() ;
}

Затем называется:

Func() ;
Func2() ;

Второй звонок Func() с помощью Func2() было бы почти конечно место местное fooStruct.foo по другому адресу в стеке из-за кадра стека для Func2, поэтому не будет иметь то же значение, что и случайно. Более того, если бы последовательность была:

Func() ;
Func2() ;
Func() ;

Третий звонок Func() может быть использовать то же расположение стека, что и первое, но это пространство будет наверное были изменены Func2() (из-за инициализированных переменных), так что, скорее всего, вы больше не будете наблюдать то же значение в fooStruct.foo,

Что это неинициализированные средства; вы получаете то, что происходит там. И поскольку, когда переменная выходит из области видимости, она, как правило, не изменяется, такие значения могут «появляться» (и не обязательно в одной и той же переменной) — просто потому, что это самая простая и эффективная реализация (т.е. ничего не делать).

4