OberonCore https://forum.oberoncore.ru/ |
|
Классика жанра https://forum.oberoncore.ru/viewtopic.php?f=27&t=3478 |
Страница 1 из 1 |
Автор: | Сергей Губанов [ Суббота, 11 Июнь, 2011 00:25 ] |
Заголовок сообщения: | Классика жанра |
На работе убил полдня на возню со странным багом. Есть двухсвязный список, организуется указателями first, last и у каждого элемента prev и next. Объекты в своих "конструкторах" сами себя в этот список добавляют, а в "деструкторах" из списка самоудаляются. Таким образом есть инвариант: в списке нет "трупов" (то есть объектов у которых был вызыван "деструктор"). Теперь начинается самое интересное. Во время работы программы в списке иногда всё-таки обнаруживается "труп". Код достаточно тривиальный. Методом пристального вглядывания перепроверил его сто раз, ошибки не нашёл. Стал думать на нарушение потокобезопасности. Перепроверил, не нарушается. Так пока и не разгадал. Программировал бы на Сях подумал бы на порчу памяти, но я на C# в микрософтовском дотнете, вроде не должно. Хотя, конечно, полностью исключать глюк дотнетного рантайма всё же нельзя. |
Автор: | alexus [ Суббота, 11 Июнь, 2011 01:13 ] |
Заголовок сообщения: | Re: Классика жанра |
Сергей Губанов писал(а): На работе убил полдня на возню со странным багом. Есть двухсвязный список, организуется указателями first, last и у каждого элемента prev и next. Объекты в своих "конструкторах" сами себя в этот список добавляют, а в "деструкторах" из списка самоудаляются. Таким образом есть инвариант: в списке нет "трупов" (то есть объектов у которых был вызыван "деструктор"). Теперь начинается самое интересное. Во время работы программы в списке иногда всё-таки обнаруживается "труп". Может быть Вы столкнулись с феноменом параллельной работы конструкторов и деструкторов?.. Поясню на вероятном примере:Код: Есть список А=В=С [Примечание. Время Т=2 примерно равно времени Т=1, а время Т=4 чуть больше времени Т=3. Примерное равенство времен означает, что объекты "видят" одну и ту же карту памяти. "Чуть большее время" означает, что второй объект пишет в память после изменений, сделанных первым объектом, но при этом самих изменений он не видит, поскольку не перечитывает карту памяти].Т=1 Вызван деструктор объекта В Т=2 Вызван конструктор нового объекта D (объект В еще не удален и D объект его "видит" и пытается вставить себя перед ним - между А и В) Т=3 Деструктор В делает A.Next := C; C.Prev := A; Т=4 Конструктор D делает A.Next := D; D.Next := B; B.Prev := D; D.Prev := A; Ссылка B.Next -> C, как правило не затирается... Таким образом, объект В себя удалил, но объект D снова поместил его в список (обратная связь не указывает на объекты В и D, они "видны", только при прямом проходе, но можно смоделировать ситуацию, когда и обратная связь будет содержать объекты B и D). Если эта гипотеза имеет право на существование, то самый простой выход из ситуации, передать управление списком отдельному объекту, который сериализует (выполнит строго последовательно) обращения от списочных объектов на вставку, удаление и перемещение по списку. Что в общем-то правильнее... для значительного числа случаев. |
Автор: | Сергей Губанов [ Суббота, 11 Июнь, 2011 16:49 ] |
Заголовок сообщения: | Re: Классика жанра |
Выспался. Кажись дошло. Два удаления подряд. Код: x = list.First; while (x != null) { tmp = x.Next; DoSomethingAndMayBeDelete(x); x = tmp; } Процедура DoSomethingAndMayBeDelete(x); иногда могла удалить более одного элемента, в том числе и два подряд, после чего указатель tmp указывал на уже удаленный объект. В списке "трупов" не было, "труп" был во временной переменной цикла. |
Автор: | alexus [ Суббота, 11 Июнь, 2011 18:53 ] |
Заголовок сообщения: | Re: Классика жанра |
Сергей Губанов писал(а): Выспался. Кажись дошло. Два удаления подряд. ![]() Ну, вот... всегда так... "ларчик просто открывался", а я тут развел... ![]() |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |