tgoop.com/gdb_dbg/25
Create:
Last Update:
Last Update:
А был ли крэшлог? (часть 2)
Итак, о чем же говорил этот аномальный крэшлог? Если все максимально упростить и немного обфусцировать, то взрывающийся кусок кода выглядит так:
struct Info info;
assert(info.isValid());
// код (включая вызовы других функций), работающий со структурой info, но никак не меняющий ее поля
info.address.foo(); <--- SEGFAULT
При этом вызов
isValid()
как раз и призван гарантировать, что info
сконструирована корректно, к полю address
доступаться можно, вызывать foo()
- тоже. Но именно при попытке вызывать foo()
все и бахает.В сгенерированном коде это выглядит так:
1) Структура Info разложилась на
address
лежит на регистре x29 (все происходит на arm64, так что регистров много);2) Действительно, больше никто не трогает x29 на протяжении всего исполнения метода;
3) Между загрузкой
address
на x29 и его использованием (и развалом) происходит много вызовов, но это не проблема: x29 - неволатильный, а значит это ответственность вызываемого метода сохранять его при необходимости. Т.е. никакой вызов x29 попортить тоже не мог.При этом в крэшлоге написано, что на момент взрыва в x29 была единичка, а никакой не адрес. Если бы она была там изначально, то
isValid()
вернул бы false
, упал бы ассерт. Так кто же испортил x29?—
Был бы у нас воспроизводящий пример, все было бы сильно проще: ставим watch на соответствующую память и аккуратно смотрим, кто же злодей (тоже задачка не самая простая, т.к. пришлось бы записать трассу изменений, ведь любой вызываемый метод мог бы сохранять x29 у себя в прологе и потом восстанавливать), но ведь у нас нет примера, только крэшлог!
Впрочем, зная конкретное место в коде, где все взрывается, можно и пример постараться написать самому, стрессуя именно его. Чем я и занялся, через какое-то время получив кролика (так мы в команде называем маленькие примеры для воспроизведения проблемы). Развал и на нем воспроизводился не всегда, но мне достаточно всего двух раз, спасибо соответствующим отладочным тулам. Например, rr time-travel debugger: потрясающая штука, которая позволяет записать исполнение и потом получить стабильно воспроизводящийся баг (а еще ходить назад во времени при отладке, чудо-чудесное).
Так что через пару-тройку часов получилось таки поймать вредителя с поличным ↓
BY Алло, это отладочная?
Share with your friend now:
tgoop.com/gdb_dbg/25