Приделал к проекту очередную фишку. Было свободное время, т.к. коллега свою часть ещё не доделал. Дай, думаю, посмотрю, какие предупреждения выдаёт компилятор. Я человек простой -- предупреждения компилятора, как правило, игнорирую. Но знаю одного человека, который не начинает отладку, пока не избавится от всех предупреждений.

Так вот, он прав.

Короче говоря среди кучи declared but never used и incompatible pointer type (я слышу возглас из зала: "тебе пора переходить на Rust!") я обнаружил действительно серьёзную вещь. "returning pointer to local variable".

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

Автор кода выделял динамический массив:

int a=new int[n];

Я же, поскольку адаптировал код под микроконтроллер, благоразумно решил отказаться от динамической памяти. Нет, в микроконтроллерах эта механика всё равно работает, но мне опытные товарищи советовали не использовать её. Кроме того, я был уверен, что данная функция не будет эксплуатироваться при размере массива больше трёх (это была математическая функция). Поэтому я заменил строку выше на такую:

int a[3];

И удалил строку с освобождением памяти. А что происходит с этим массивом -- не посмотрел. В общем, он возвращался из функции:

return a;

И если при динамическом выделении памяти всё было бы хорошо, то при локальном (автоматическом) выделении памяти всё становится плохо. Функция завершается, освобождает память на стеке, а вызывающая функция начинает обращаться к ничьей области памяти.

* * *

Коллега по этой ситуации предложил интересную аналогию: представь себе, что ты дома положил на стол сотовый телефон и пошёл на работу. А на работе у себя на столе начинаешь его искать в том же месте, но почему-то не находишь!