Переполнение в C ++ функции Unordered_set - PullRequest
0 голосов
/ 12 октября 2018

TBH, я удивлен, я задаю этот вопрос, но смотрю на этот код

template <class _Tp, class _Hash, class _Equal, class _Alloc>
void
__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
{
    if (__n == 1)
        __n = 2;
    else if (__n & (__n - 1)) // >>>>>>LINE IN QUESTION<<<<<<<<<<<
        __n = __next_prime(__n);
    size_type __bc = bucket_count();
    if (__n > __bc)
        __rehash(__n);
    else if (__n < __bc)
    {
        __n = _VSTD::max<size_type>
              (
                  __n,
                  __is_hash_power2(__bc) ? __next_hash_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
                                           __next_prime(size_t(ceil(float(size()) / max_load_factor())))
              );
        if (__n < __bc)
            __rehash(__n);
    }
}

В этой строке выше следует разрешить нулевой __n, что - 1 рядом с ним приводит кцелочисленное переполнение, которое отлавливает отладчик (в моем случае XCode) и жалуется.Теперь я понимаю, что операция & в этой строке может сделать строку в целом по-прежнему актуальной для процесса хеширования.Но что сделали другие, чтобы обойти это?Молчать отладчик?Вызов функции, который сделал это, был другим вызовом библиотеки std:

template <class _Value, class _Hash, class _Pred, class _Alloc> 
     unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(const unordered_set& __u)
     : __table_(__u.__table_){
        #if _LIBCPP_DEBUG_LEVEL >= 2
           __get_db()->__insert_c(this);
        #endif
           __table_.rehash(__u.bucket_count()); // >>FUNCTION CALL<<<<
           insert(__u.begin(), __u.end());
      }

Здесь __u.bucket_count() возвращает ноль и, таким образом, происходит соответствующее поведение.Предупреждение об ошибке или дезинфицирующем средстве, которое я получил дезинфицирующим средством Неопределенное поведение в XCode, было Unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned long'

1 Ответ

0 голосов
/ 13 октября 2018

Похоже, что об этом было создано сообщение об ошибке, и один из разработчиков ответил на него здесь https://bugs.llvm.org/show_bug.cgi?id=38606 Кажется, что операция выполняет проверку, чтобы определить, является ли она степенью 2. Этот код является очень намеренным.

Согласно этому билету, https://bugs.llvm.org/show_bug.cgi?id=25706, кажется, что они проходят и заставляют замолчать все такие интересные события в стандартной библиотеке.

Так что, я думаю, это мой ответ.Либо подожди, пока они его заставят замолчать, либо я сам смогу заставить его замолчать, если не проигнорирую.

...