Функция map небезопасна
- Войдите на сайт для отправки комментариев
Приветствую всех!
Выловил баг, или даже не баг, а возможную конфликтную ситуацию при использовании функции map.
Стояла задача нарисовать на экранчике прогресс-бар чтения файла с SD карты.
вот пример кода:
uint8_t progress_width = map(music_file.position(), 0, music_file.size(), 0, 100);
[пояснение для новичков: эта функция вычисляет ширину прогресса от 0 до 100 попугаев в зависимости от размера файла ( music_file.size() ) и той позиции, где сейчас читается файл (music_file.position() ). ]
В случае, если размер файла = 0 (битый, пустой, карточка барахлит итд) получается деление на ноль.
Внутри эта функция устроена так (файл WMath.cpp):
long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long dividend = out_max - out_min;
const long divisor = in_max - in_min;
const long delta = x - in_min;
return (delta * dividend + (divisor / 2)) / divisor + out_min;
}
и получается, что uint8_t progress_width = map(music_file.position(), 0, 0, 0, 100); пытается значение
(delta * dividend + (divisor / 2)) разделить на divisor + out_min , а divisor и out_min = 0
Будьте осторожны.
ну так переписать чтобы не было деления на ноль, то-есть размер файла брать большим из 1 или длины файла
Код уже исправлен, добавлена проверка на размер файла.
Просто такая ситуация может возникнуть у новичков.
SuperXL, а какова, по Вашему мнению, должна быть "ширина прогресс-бара" при длине файла равной нулю?
Назовите число.
Вывод: функция map в данном случае совершенно ни при чем. А вот автор кода забыл сделать необходимую проверку. Такая проблема может возникнуть с любой другой функцией при использовании подобного стиля программирования.
Т.е. небезопасна совсем не функция map, а стиль программирования, пренебрегающий проверками.
Код уже исправлен, добавлена проверка на размер файла.
Просто такая ситуация может возникнуть у новичков.
и дальше что? по нормальному нужна функция обработчик ошибок, если при открытии файла длина равна нулю, возвращаем в обработчик соответствующий код ошибки и далее ветвить программу в соответствии с кодом ошибки, в вашем случае видимо перейти к открытию другого файла...но ситуации могут быть разные...типичная олимиадская задача... wdrakula сможет откомментировать авторитетно, он сильно в теме )))
Ну, разделить-то она пытается только на divisor, out_min потом уже из результата вычитается.
А что получается-то? Вы пробовали?
Собственно и оператор / небезопасен. У любого новичка с ним могут возникнуть проблемы ))
Народ, придумываем новый, безопасный ?
Народ, придумываем новый, безопасный ?
Конечно, что бы углы в радианах на циферблатах можно было в разных диапазонах менять, например.
SuperXL, а какова, по Вашему мнению, должна быть "ширина прогресс-бара" при длине файла равной нулю?
Назовите число.
По моей логике, если файл имеет нулевой размер то и ширина бара тоже должна быть равна нулю. Что и реализовано в куске кода выше.
Вывод: функция map в данном случае совершенно ни при чем. А вот автор кода забыл сделать необходимую проверку. Такая проблема может возникнуть с любой другой функцией при использовании подобного стиля программирования.
Т.е. небезопасна совсем не функция map, а стиль программирования, пренебрегающий проверками.
Согласен с Вами, что подобный подход к написанию кода является нежелательным. Автор кода, который написал функцию map мог, действительно, написать проверку на предмет ситуации деления на ноль. Только вот каков результат должна вернуть эта функция - спорный момент. Опять по моей же логике, хотя случаи разные бывают, функция должна вернуть long out_min, если мы говорим о том, что out_min < out_max.
В моем случае, ESP32 просто уходила в "кернел_1 паник" с указанием на то, что где-то есть деление целого числа на ноль. Возможно, дебагер показал бы где затык, но не имея онного пришлось, отслеживать Serial.print-ами.
и дальше что? по нормальному нужна функция обработчик ошибок, если при открытии файла длина равна нулю, возвращаем в обработчик соответствующий код ошибки и далее ветвить программу в соответствии с кодом ошибки, в вашем случае видимо перейти к открытию другого файла...но ситуации могут быть разные...типичная олимиадская задача... wdrakula сможет откомментировать авторитетно, он сильно в теме )))
я привел совсем меленький кусочек кода, который вычисляет ширину бара, естественно есть еще и до и после. Отрисовка бара идет через функцию из задачи повторяющейся с интервалом 200 мс. И эта функция отвечает только за вычисление/отрисовку, все проверки, флаги разрешения и прочее ранее.
По поводу олимПиадских задач, мимо. Это не про меня. Я делаю свой девайс. Ну нравится мне кулибничать да паялить чё-нить.
Ну, разделить-то она пытается только на divisor, out_min потом уже из результата вычитается.
А что получается-то? Вы пробовали?
Получается то, что ESP32 вываливается в "кернел_1 паник", я выше написал, как это выглядит. Если честно, не совсем Вас понял про то, что пробовал ли я что-то. Если Вы про то, что посчитать конечный результат функции, то да.
Новичек на то и новичек, чтобы творить, ошибаться и учиться, по большей степени, на чужих ошибках.
А вот есть идея, что деление на ноль должно давать бесконечность, ибо в любом числе бесконечное количество нулей. И тогда получается, что при нулевом размере файла градусник должен показывать максимально возможное значение.
Очень рекомендую смотреть, что конкретно пишет esp, а она вам прям конкретно пишет ошибку. Просто нужно уметь это читать. Более того, скажите спасибо, что есп так делает. Другие процы молча пичкают возвращаемую переменную дерьмом, не побоюсь этого слова.
А вот есть идея, что деление на ноль должно давать бесконечность, ибо в любом числе бесконечное количество нулей. И тогда получается, что при нулевом размере файла градусник должен показывать максимально возможное значение.
Очень рекомендую смотреть, что конкретно пишет esp, а она вам прям конкретно пишет ошибку. Просто нужно уметь это читать. Более того, скажите спасибо, что есп так делает. Другие процы молча пичкают возвращаемую переменную дерьмом, не побоюсь этого слова.
:-) Согласен с Вами, что деление на ноль дает бесконечность, но, как Вы сказали при нулевом размере файла градусник должен показывать бесконечно нулевой размер. ))
ESP-шка мне и написала, что идет где-то деление на ноль целого числа. Полез разбираться, где идет именно деление, вышел на map. Залез под капот функции map и обнаружил, то что описал в первом посте.
Бесконечно нулевой, это стремящийся к нулю. А бесконечный это все же стремящийся к бесконечно большому значению.
Стремящийся к нулю - это бесконечно малый.
Насколько далеко от нуля бесконечно малое значение ?
Вопрос некорректный.
Главное другое - бесконечно малое никогда не равно нулю.
Всю математику перекроили, рамануджаны млять.
Деление на ноль не сходится.
Числа "бесконечность" нет.
Бесконечно малое (в контексте близкое к нулю) это ноль.
А если в контексте операции "меньше", то не сходится.
Насколько далеко от нуля бесконечно малое значение ?
Отличается менее чем на эпсилон.
Деление на ноль не сходится.
Числа "бесконечность" нет.
? ?? ???? ????????
...ушел сдавать в макулатуру диплом МехМата.
Насколько далеко от нуля бесконечно малое значение ?
Бесконечно близко :-)
Деление на ноль не сходится.
Числа "бесконечность" нет.
? ?? ???? ????????
...ушел сдавать в макулатуру диплом МехМата.
Не примут. Жесткий сильно. Используй как подставку под сковородку.
Бесконечно близко :-)
Хорошо, плюсанул :)
Всю математику перекроили, рамануджаны млять.
Деление на ноль не сходится.
Числа "бесконечность" нет.
Бесконечно малое (в контексте близкое к нулю) это ноль.
А если в контексте операции "меньше", то не сходится.
Как всегда без аргументов и сплошной поток мысли... С чем не сходится, с представлением о мире ?
Вопрос некорректный.
Главное другое - бесконечно малое никогда не равно нулю.
Бесконечно малое не равно нулю, но с ним сравнимо и близко, как уже ответили - бесконечно близко. Так что нифига , ни разу не главное и вопрос обычный, нормальный. Вот если бы я спросил сколько гвоздей на рассвете, было бы не корректно.
Главное другое - бесконечно малое никогда не равно нулю.
Тут мы всегда с "математичкой" ругались, потому что "физичка" была за нас :-)
Ведь с любой желаемой степенью точности это бм можно считать нулём.
Ведь с любой желаемой степенью точности это бм можно считать нулём.
А как же Вы разрешали парадокс Зенона? Он ведь в конечных величинах неразрешим.
А они вместо этого в "Соки-воды" ходили и каждый просил тетеньку налить ему половину того, что было выдано предыдущему.
Ведь с любой желаемой степенью точности это бм можно считать нулём.
А как же Вы разрешали парадокс Зенона? Он ведь в конечных величинах неразрешим.
:-)
Зенон пренебрегал тем, что любой реальный объект нельзя дробить до бесконечности. Он явно думал, что имея буханку хлеба и нож можно целую вечность одно делить другим пополам, просто он не видел мешок зерна.
Физически есть абсолютный ноль, а математически?
Вопросов больше чем ответов...
Что точнее 0 или 0.0 или 0.00 или ... ?
Если есть 0 есть ли -0? Насколько они бесконечно близки друг другу?
Как правильно писать ноль, нуль или зеро?
Если есть 0 есть ли -0? Насколько они бесконечно близки друг другу?
В программировании, конечно есть. Причём, 0 > -0 даёт истину.
А на Зенона попрошу не катить. Этот человек в 1-ом веке н.э. сделал первое (из известных) программируемое устройство и научил мальчика (своего подмастерье) его программировать. Так что он великий предок всех программистов. Кроме того, он же сделал первый в истории торговый автомат ("wendig machine" на языке
потенциального противниканаших уважаемых партнёров). Так что автоматизаторы торговли его тоже свои родоначальником считают. Ну и, наконец, он создал хиробаллисту, которая под названием "Скорпион" стояла на вооружении римской армии около 500 лет - никем до сих пор не побитый рекорд ВПК.Не знал, мне запомнился по апории про бегуна и черепаху.
Физически есть абсолютный ноль, а математически?
Наоборот: физически - нет, а математически - есть.
Вопросов больше чем ответов...
Что точнее 0 или 0.0 или 0.00 или ... ?
Если есть 0 есть ли -0? Насколько они бесконечно близки друг другу?
Как правильно писать ноль, нуль или зеро?
0.(0)
А начиналось все с градусника.....
Нет, не так. "А как хорошо начиналось...")
Нет, не так. "А как хорошо начиналось...")
ты лучше озвучь где купаться небезопасно )
Везде! Если умеешь плавать.) Однажды купался в хороший шторм, так зеваки благодарили, говорили что они за меня болели (выплыву - потону))).
На самом деле, дурак - дураком! Эх, тогда бы теперешние мозги...(