LINUX.ORG.RU

bison + pointers = UB ?

 , , ,


0

4

Доброго времени суток!

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

Файлы проекта вот тут.

Проблема такова:

если в syntax.ypp раскомментировать 234 строку и в 185 добавить delete tmp;, то интерпретатор начинает сыпаться, например, на таком коде (для отладки грамматики пока просто интерпретатор собирает команды в списки и потом выводит их):

> ty && kl
ty && kl
> hj && io ||
| jk &&
| kll
io && io || jk && kll

Последняя строчка должна быть такой: hj && io || jk && kll

Или вот так вот сыпется (добавлено отладочное сообщение о вызове деструктора списка):

> ty && io || kl
ty && io || kl
destructor 0 ty
destructor 1 io
destructor 2 kl
destructor 1 io
destructor 0 ty
> ty && hj &&
destructor 1 hj
| jk
Ошибка сегментирования (сделан дамп памяти)

То есть почему-то при трех аргументах в первом конвейере, вызывается деструктор одного из элементов во втором конвейере.

Второй день в глаза долблюсь - не вижу причин такой странной работы new/delete в bison. Как мне корректно почистить память?

★★

Ну может еще какие-то косяки есть, которые я не заметил. Если укажете их - тоже хорошо.

aido ★★
() автор топика
std::shared_ptr<conveyor> prev_link;
std::shared_ptr<conveyor> next_link;

Это же цикл, память не будет освобождена сама по себе из-за него.

delete tmp;
А это явное удаление объекта, владение которым отдано std::shared_ptr, что ведёт к UB (std::shared_ptr его потом ещё раз попытается удалить).

Ссылки должны быть в одном направлении, в обратном можно std::weak_ptr, либо std::unique_ptr в одну сторону, а назад обычные указатели.

Также не понятно, почему не использовать стандартные контейнеры или хотя бы уже везде передавать std::shared_ptr, было бы проще.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Также не понятно, почему не использовать стандартные контейнеры или хотя бы уже везде передавать std::shared_ptr, было бы проще.

То есть?

aido ★★
() автор топика
Ответ на: комментарий от aido

Из правил возвращать не T*, а std::shared_ptr<T> и складывать, например, в std::vector<std::shared_ptr<T>> (если подходит по операциям).

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Ссылки должны быть в одном направлении, в обратном можно std::weak_ptr, либо std::unique_ptr в одну сторону, а назад обычные указатели.

Спасибо, это проблему решило.

P.S. отладка пока в процессе. to be continued.

aido ★★
() автор топика
Ответ на: комментарий от xaizek

если у меня поле структуры (указатель) не под shared_ptr, то при удалении структуры объект, на который указывает это поле ведь тоже должен удалиться?

aido ★★
() автор топика
Ответ на: комментарий от aido

Я про то, что можно не реализовывать список самому, а использовать готовую реализацию из стандартной библиотеки, если нет причин поступать иначе.

xaizek ★★★★★
()
Ответ на: комментарий от aido

Нет. Сырой указатель сам ничего не удаляет. Тут либо использовать std::unique_ptr, либо явно удалять тот объект в деструкторе этой структуры. Первое предпочтительнее.

xaizek ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.