имя, прозвище, кличка или что-то в этом роде. (_glav_) wrote,
имя, прозвище, кличка или что-то в этом роде.
_glav_

Categories:

c++ undefined behavior

Поймал давеча два бага, связанные с "непредсказуемым" поведением в детерминированном коде. С одним возился несколько дней, т.к. место, в котором ошибка проявлялась, было совершенно не там, где ошибка находилась. Второй обнаружил быстро, но тоже неожиданно.

Тот, что попроще, выглядел примерно так, как описано тут: при удалении массива программа "зависает" и, судя по отладчику, количество выделенной памяти не уменьшается. Увидев схожее поведение, я обнаружил и ошибку: действительно, при работе с массивом я обращаюсь к памяти за его пределами. То, что обращение к "не своей" памяти приводит к непредсказуемым эффектам в момент обращения, это я знаю. А вот то, что такое обращение может повлиять на процесс освобождения этой памяти гораздо позже этого обращения, оказалось неожиданным. Я так понимаю, как конкретно хранить размер массива - это compiler-specific поведение, и в моём случае массив просто завершается неким стоп-символом, типа '\0'. Обращаясь к следующему за последним элементом массива я затираю этот стоп-символ, так что оператор delete[] либо пытается освободить вообще всю доступную память, либо просто начинает грустить.

Второй баг связан с тем, что я использовал метод std::sort вместе с дефолтным оператором сравнения для сортировки пары std::pair<double,MyClass>. Число double - не уникальный идентификатор, но случайное число в достаточно широком диапазоне. Каким-то образом так сложились звёзды, что два случайных числа оказалсь одинаковыми, а std::sort не гарантирует сохранения порядка элементов в этом случае. Если бы сортировались просто числа, это не имело бы никакого значения, но я сортирую пары, которые содержат объект MyClass, каждый из которых уникальный. Из-за этого примерно в половине случаев после сортировки я получал список (..., object1, object2, ...), а в другой половине случаев - (..., object2, object1, ...), что создавало две альтернативные timelines. В нормальной ситуации это должно было бы обнаружиться сразу в момент расщепления timelines. Но меня интересует поведение не отдельных объектов, а их статистические свойства. В течение некоторого времени после расщепления timelines каждый из объектов продолжал жить своей жизнью, не оказывая никакого влияния на общую статистику, - до тех пока пока две timelines не разошлись достаточно далеко. Место и время, в которых эта разница проявилась, никак не указывали на настоящую локацию расщепления timelines, тем более на причину этого расщепления, так что пришлось повозиться. В итоге переключился на std::stable_sort и собственный оператор сравнения, что и решило исходную проблему.

This entry was originally posted at https://glav.dreamwidth.org/678892.html. Please comment there using OpenID.
Tags: it, lytdybr
Subscribe

  • Есть статистика, - а есть журналисты

    Вот отличный пример [Исследователи] тестируют случайным образом выбранные 100 инфекций в невакцинированных людях и видят там 10 инфекций вариантом…

  • "здесь так принято" или культура

    Есть известная история про обезьян, бананы и холодный душ, которая обычно призвана иллюстрировать "стадность" людей и бездумное следование…

  • wokeism как DDOS атака

    Внезапно подумал, что современная пандемия wokeism'а - есть результат DDOS-атаки на бюрократическую систему. Бюрократическая система работает…

Comments for this post were disabled by the author