Чистый способ запуска современного кода C++ при выходе из функции, если он может выдать ошибкуC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Чистый способ запуска современного кода C++ при выходе из функции, если он может выдать ошибку

Сообщение Anonymous »

Я пишу службу Windows на C++ (Visual Studio 2022, C++20), и служба неожиданно завершилась в полевых условиях. Это было связано с обновлением, которое я сделал спустя много времени после написания исходного кода, где внутренней функции f требовался установленный флаг на время ее выполнения, а затем возвращался в неустановленное состояние при выходе из функции. Чтобы внести это изменение, я просто добавил пару строк кода, как показано ниже — SetFlag(true) иscope_guard:

Код: Выделить всё

void outer() {
while(true) {
try {
many_nested_functions_leading_to_f();
}
catch (const MyException&) {
/* handle exception and then retry with the outer while loop */
}
}
}

void SetFlag(bool) {
/* can throw MyException */
}

void f() {
/* We need flag to be true for the duration of this function */
SetFlag(true);
auto guardClearFlag = sg::make_scope_guard([] { SetFlag(false); });

/* complicated flow control, many return paths .. */
}
предназначен для выдачи ошибок, и в этом случае я хочу, чтобы выполнение возобновилось вверх по стеку вызовов внешней функции, где я очищаю и затем повторяю попытку, повторяя цикл while. Это, конечно, классическая проблема, когда деструкторы выдают ошибку, и я потратил некоторое время на то, чтобы разобраться в технических деталях и лучших практиках.
В моем случае я обнаружил, что самым простым и понятным решением было обернуть f кодом, который устанавливает и очищает флаг:

Код: Выделить всё


void fWithFlagTrue() {
/* complicated flow control, many return paths .. */
}

void f() {
SetFlag(true);
fWithFlagTrue();
SetFlag(false);

}
Это было довольно неудовлетворительно, потому что:
  • Мне очень нравится мой оригинальный двухстрочный патч. Я устанавливаю флаг вверху, и с помощьюscope_guard я могу гарантировать, что флаг будет очищен при выходе из функции.
  • Мне действительно не нравится мое решение, поскольку в нем много шаблонов, и кажется, что должно быть менее утомительное идиоматическое решение.
Я понимаю, что иметь два активных исключения одновременно проблематично, а прерывать раскрутку стека - это очень проблематично. В моем случае, если f выдает ошибку, я хочу, чтобы выполнение завершилось во внешнем, как я описал выше, и состояние флага не имеет значения. Если SetFlag выдает то же самое: я просто хочу, чтобы выполнение заканчивалось внешним. Поэтому я думаю, что мое решение многословно, но это то, чего я хочу логически. Я просто надеюсь, что есть что-то близкое к моему оригинальному двухстрочному патчу, который сможет достичь этой цели.

Подробнее здесь: https://stackoverflow.com/questions/798 ... -may-throw
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»