it — итератор мультимапа. В процессе перебора элементов выясняется что текущее значение it указывает на элемент который надо освободить и убрать из мульмапа.
я делаю:
delete it->second <- Тут освобождается объект типа А
потом делаю it = my_multimap.erase(it);
Так можно ? Я замучан багом Это единственное подозрительное место!
В принципе все работает, но иногда, очень редко в конце работы после тотальной итерации уничтожения счетчик объектов указывает что парочка объектов типа А еще жива.
Здравствуйте, кубик, Вы писали:
К>it — итератор мультимапа. В процессе перебора элементов выясняется что текущее значение it указывает на элемент который надо освободить и убрать из мульмапа. К>я делаю:
К>delete it->second <- Тут освобождается объект типа А К>потом делаю it = my_multimap.erase(it);
К>Так можно ?
Если у тебя там сырой указатель, который последним указывает на конкретный экземпляр типа A (то есть, если вся мультимапа имеет какой-то такой тип: std::multi_map<key_type, A*>), то можно и нужно.
Другое дело, что откуда там вообще взялся delete и сырой указатель в 2020-м году?! Использование delete не должно выходить за пределы реализации библиотек по управлению памятью.
То есть почему у тебя изначально не std::multi_map<key_type, std::unique_ptr<A>>, например? Тогда и явный delete не нужен, и за удалением сам unique_ptr проследит и не забудет его сделать.
Здравствуйте, кубик, Вы писали:
К>it — итератор мультимапа. В процессе перебора элементов выясняется что текущее значение it указывает на элемент который надо освободить и убрать из мульмапа. К>я делаю: К>delete it->second <- Тут освобождается объект типа А К>потом делаю it = my_multimap.erase(it);
Если тип значения в мапе это голый указатель — это нормально, но тогда подозрительно само использование голого указателя (проблемно ситуациями с потерей при вылетающих исключениях).
Если что-то другое, то erase() должно вызвать удаление (сюда включается какой-то объектный тип напрямую и варианты типа unique_ptr, shared_ptr).
Само же присвоение типа it = my_multimap.erase(it) не имеет явной проблемы.
К>Так можно ? Я замучан багом Это единственное подозрительное место! К>В принципе все работает, но иногда, очень редко в конце работы после тотальной итерации уничтожения счетчик объектов указывает что парочка объектов типа А еще жива.
Всес спасибо за ответы.
Попутал ночью после многонедельного дебага.
Естественно так можно делать.. просто думать не начто, уже дебагбриков навтыкал.
Приложение было написано много лет назад старинными мастерами и работало отлично. После этого на протяжении многих лет засиралось велосипедами и костылями.
Теперь я должен победить все известные баги.
netch, Да, тут многониточность, но именно этот мультимэп обёрнут в rw локи. Если оберну только в W локи боюсь баг зароется глубже ... хотя .. чего мне еще боятся ..
Здравствуйте, кубик, Вы писали:
К>netch, Да, тут многониточность, но именно этот мультимэп обёрнут в rw локи. Если оберну только в W локи боюсь баг зароется глубже ... хотя .. чего мне еще боятся ..
Ну тогда проблема скорей всего не в мультимэпе а в том как объекты используются из разных потоков.
Может быть те объекты, которые надо удалить, уже "убиты" каким-нибудь образом при использовании из разных потоков.
Здравствуйте, кубик, Вы писали:
К>Приложение было написано много лет назад старинными мастерами и работало отлично. После этого на протяжении многих лет засиралось велосипедами и костылями.
Обожаю такие вещи.
К>Теперь я должен победить все известные баги.
Накачивай код ассертами.
Обнуляй указатели после delete.
Переводи динамические объекты на счетчики ссылок (но здесь нужно уметь с ними работать).
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, кубик, Вы писали:
К>Попутал ночью после многонедельного дебага. К>Естественно так можно делать.. просто думать не начто, уже дебагбриков навтыкал.
Пробовал использовать valgrind (если пишешь под Linux) или CRT (если пишешь под Windows)? Если пробовал, что они пишут?
Друзья, баг нашелся!
Проблемма была в некачественном использовании rw-локов. Они кастомные и никто не озабочивался проверять returned value. Иногда они не лочили....
Начал проверять что б после каждого инсерта в мультимап size() должен увеличиваться на 1, ну и обнаружилось несоответствие.
watchmaker, спасибо, все переделано на boost::shared_ptr!
Здравствуйте, AleksandrN, Вы писали:
AN>Пробовал использовать valgrind (если пишешь под Linux) или CRT (если пишешь под Windows)? Если пробовал, что они пишут?
valgrind посоветовал в тему, а вот CRT тут немного сбоку.
Для винды есть кастрированный аналог valgrind — DrMemory https://drmemory.org/ Запускает твоё приложение в своей виртуальной машине (но с jit-компиляцией), старается полностью контролировать обращения к памяти.