Почему исключение EXCEPTION_FLT_OVERFLOW должно создаваться при присвоении double или изменении значения присвоенного double?

#c #windows #qt #double

#c #Windows #qt #double

Вопрос:

Я встречаю два разных дампов strange и weird, которые оба связаны с двойным присвоением.

Предыстория

Существует QJsonValue(Qt5.0), похожее на это:

 /*!
    Assigns the value stored in a other to this object.
 */
QJsonValue amp;QJsonValue::operator =(const QJsonValue amp;other)
{
    if (t == String amp;amp; stringData amp;amp; !stringData->ref.deref())
        free(stringData);

    t = other.t;
    dbl = other.dbl;

    if (d != other.d) {

        if (d amp;amp; !d->ref.deref())
            delete d;
        d = other.d;
        if (d)
            d->ref.ref();

    }

    if (t == String amp;amp; stringData)
        stringData->ref.ref();

    return *this;
}
  

И затем, есть некоторая операция, подобная этой, она вызовет метод, описанный выше.

 void test(QJsonObject obj, const QStringamp; key)
{
    QJsonValue value = obj.value(key);
}
  

Dump1

Произошел сброс в dbl = other.dbl; .

Информация об исключении этого дампа является:

Поток попытался прочитать или записать на виртуальный адрес, для которого у него нет соответствующего доступа.

Почему операция, которая просто копирует значение из other.dbl в this.dbl , вызовет исключение?

введите описание изображения здесь

Dump2

Это также связано с операцией dbl = other.dbl .

Было так странно, что значение this.dbl не совпадает со значением other.dbl .

введите описание изображения здесь

PS

Интересно, что operator = метод QJsonValue в Qt5.12 изменился, и я не знаю почему.

 /*!
    Assigns the value stored in a other to this object.
 */
QJsonValue amp;QJsonValue::operator =(const QJsonValue amp;other)
{
    QJsonValue copy(other);
    swap(copy);
    return *this;
}

/*!
    fn QJsonValue amp;QJsonValue::operator =(QJsonValue amp;amp;other)
    since 5.10

    Move-assigns a other to this value.
*/

/*!
    fn void QJsonValue::swap(QJsonValue amp;other)
    since 5.10

    Swaps the value a other with this. This operation is very fast and never fails.
*/
  

Комментарии:

1. Я не слишком знаком с VS, но вы уверены, что не присваиваете значение nullptr? В вашем первом примере присваиваемый адрес является 0x43EF довольно низким. Вы могли бы assert(this != nullptr) проверить это.

2. В первом примере, amp;dbl = 0x00cfceac {0.00000000000000000} и amp;dbl = 0x00cfcd4c {8.416762146484e-315#DEN} . this не будет nullptr , потому что объект определен в stack. Я не знаю, что 0x43EF означает адрес и как он генерируется.

3. Если вы посмотрите внимательно, нарушение доступа на запись во втором примере произошло во время stringData->ref.ref() . Смотрите желтую стрелку в левом желобе. Таким образом, проблема не относится конкретно к double assignment, это просто проблема с памятью.

4. Также вы смотрели на стек вызовов, чтобы убедиться, что вы действительно назначаете объект в стеке, а не где-то еще?

5. stringData и dbl находятся в объединении. Таким образом, причина недействительности stringData заключается в том, что значение dbl не совпадает с other.dbl . И я действительно уверен, что объект QJsonValue присваивается в стеке, точно так же, как операция, которую я пишу в вопросе.