SQLite: последовательный вызов finalize - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть функция, которая направлена ​​на удаление конкретной строки из базы данных SQLite по идентификатору UID.

Последовательность следующая:1. Создайте запрос выбора, чтобы проверить, существует ли строка2. Подготовьте запрос3. Свяжите строку UID4. Шаг5. ЗавершитьЕсли строка существует{6. Создайте запрос на удаление7. Подготовьте это8. Свяжите UID9. Шаг10. Завершить11. Завершить}

Как вы можете видеть сначала, он проверяет, существует ли строка, чтобы уведомить вызывающую сторону, если требуемый UID неверен, а затем создает новый запрос на удаление.

Программа работает как ожидалось в ~14/15 тестовых случаев.В тех случаях, когда происходит сбой программы, происходит сбой до последнего вызова завершения (11-й пункт).Я проверил все данные, и кажется, что все верно.

Вопрос в том, каково ожидаемое поведение последовательного вызова функции финализации.Я попытался установить 5 вызовов finalize один за другим, но поведение остается тем же.

1 Ответ

0 голосов
/ 20 ноября 2018

Хотя документация не нуждается в явном изложении этого, совершенно очевидно, что то, что вы делаете, - это "неопределенное поведение" (в рамках библиотеки).

Так же, как delete с динамически распределенной памятью, вы должны завершить один раз .Не дважды, не пять раз, а один раз .После того, как вы завершили подготовленное заявление, оно было «удалено» и больше не существует.Любые дальнейшие операции с этим подготовленным оператором представляют собой то, что в документации называется «серьезной ошибкой» (если мы предположим, что избыточный вызов finalize означает «использование»; а почему бы и нет?).

К счастью, есть нет причин когда-либо хотеть сделать это.Так просто, не надо!Если ваш дизайн таков, что вы потеряли контроль над потоком кода и в точке finalize по какой-то причине у вас недостаточно информации о контексте вашей программы, чтобы узнать, был ли подготовленный оператор уже завершен, это прекрасно: многокак мы делаем с указателями, вы можете установить его на nullptr, чтобы последующие вызовы не выполнялись.Но если вам нужно , чтобы сделать это, вам действительно следует пересмотреть свой дизайн.

Почему он работает для вас?Чистый шанс, очень похожий на любое другое неопределенное поведение:

Любое использование подготовленного оператора после его завершения может привести к неопределенному и нежелательному поведению, такому как ошибки сегмента и повреждение кучи.

См. Также: «Почему я не могу дважды закрыть дверцу машины, не открывая ее?» и «Почему я не могу сбрить воображаемую бороду?»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...