Действительно ли безопасный аккумулятор действительно такой сложный?

0

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

int naive_accumulator(unsigned int max,
                      unsigned int *accumulator,
                      unsigned int amount) {
    if(*accumulator + amount >= max) {
        return 1; // could overflow
    }

    *accumulator += max; // could overflow

    return 0;
}

int safe_accumulator(unsigned int max,
                     unsigned int *accumulator,
                     unsigned int amount) {
    // if amount >= max, then certainly *accumulator + amount >= max
    if(amount >= max) {
        return 1;
    }

    // based on the comparison above, max - amount is defined
    // but *accumulator + amount might not be
    if(*accumulator >= max - amount) {
        return 1;
    }

    // based on the comparison above, *accumulator + amount is defined
    // and *accumulator + amount < max
    *accumulator += amount;

    return 0;
}

EDIT: я удалил стиль смещения

  • 4
    «Сложная» версия - это на 1 строку кода больше, чем «простая» версия (если вы использовали те же правила стиля для безопасной, что и для наивной ), это не кажется слишком «сложным» ...
  • 0
    Бросьте исключение (или что-то еще), если разница между накопленным значением и максимумом больше, чем новое значение.
Показать ещё 11 комментариев
Теги:
undefined-behavior
integer-overflow

1 ответ

5
Лучший ответ

Вы считали:

if ( max - *accumulator < amount )
    return 1;

*accumulator += amount;
return 0;

Изменяя направление вашего первого сравнения в "наивной" версии, вы избегаете переполнения, т.е. Видите, сколько осталось комнаты (безопасно) и сравнивайте его с суммой, которую нужно добавить (также безопасно).

Эта версия предполагает, что *accumulator никогда не превышает max уже при вызове функции; если вы хотите поддержать этот случай, вам придется добавить дополнительный тест.

  • 0
    Я хотел бы, чтобы он поддерживал случай, когда * аккумулятор уже больше, чем max, поэтому я указал в этом вопросе без ограничений. Не могли бы вы показать мне версию, которая поддерживает неограниченный ввод? @Deduplicator подразумевает, что в моей есть ошибка.
  • 0
    @Martin добавить в начале, if ( *accumulator > max ) { /* do whatever you want to do in this case */ }
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню