Так вот, он прав.
Короче говоря среди кучи declared but never used и incompatible pointer type (я слышу возглас из зала: "тебе пора переходить на Rust!") я обнаружил действительно серьёзную вещь. "returning pointer to local variable".
Эта штука была в участке кода, который я с удовольствием скопировал из интернета. Кто же тут лоханулся, я или автор кода? Конечно же, я.
Автор кода выделял динамический массив:
int a=new int[n];
Я же, поскольку адаптировал код под микроконтроллер, благоразумно решил отказаться от динамической памяти. Нет, в микроконтроллерах эта механика всё равно работает, но мне опытные товарищи советовали не использовать её. Кроме того, я был уверен, что данная функция не будет эксплуатироваться при размере массива больше трёх (это была математическая функция). Поэтому я заменил строку выше на такую:
int a[3];
И удалил строку с освобождением памяти. А что происходит с этим массивом -- не посмотрел. В общем, он возвращался из функции:
return a;
И если при динамическом выделении памяти всё было бы хорошо, то при локальном (автоматическом) выделении памяти всё становится плохо. Функция завершается, освобождает память на стеке, а вызывающая функция начинает обращаться к ничьей области памяти.
* * *
Коллега по этой ситуации предложил интересную аналогию: представь себе, что ты дома положил на стол сотовый телефон и пошёл на работу. А на работе у себя на столе начинаешь его искать в том же месте, но почему-то не находишь!