TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #880 4.22K
​​Базовая гарантия исключений
#новичкам

Вспомним свойства базовой гарантии: после возникновения исключения в программе не должно быть утечек ресурсов и должны сохраняться все инварианты классов.

И не всегда базовой гарантии легко удовлетворить. Поскольку исключения добавляют в программу дополнительные пути выполнения кода, крайне важно учитывать последствия работы кода по таким путям и избегать любых нежелательных эффектов, которые в противном случае могут возникнуть. Давайте посмотрим на примере:

class IntArray {
int *array;
std::size_t nElems;

public:
// ...

~IntArray() { delete[] array; }

IntArray(const IntArray &that); // nontrivial copy constructor
IntArray &operator=(const IntArray &rhs) {
if (this != &rhs) {
delete[] array;
array = nullptr;
nElems = rhs.nElems;
if (nElems) {
array = new int[nElems];
std::memcpy(array, rhs.array, nElems * sizeof(*array));
}
}
return *this;
}

// ...
};


Внутренний инвариант класса IntArray - член array является валидным (возможно, нулевым) указателем, а член nElems хранит количество элементов в массиве. В операторе присваивания освобождается память текущего array'я и присваивается значение счётчику элементов nElems до выделения нового блока памяти для копии. В результате, если из new вылетит исключение, то array будет нулевым, а размер массива нет. Это нарушение инварианта и таким объектом просто небезопасно пользоваться. Метод size потенциально вернет ненулевой размер, а закономерное использование следом оператора[] приведет к неопределенному поведению.

Код, который избегает подобных нежелательных эффектов, называется exception safe. То есть предоставление базовой гарантии уже говорит о том, что ваш код "exception safe".

Допустим, что ваш класс предоставляет базовую гарантию исключений. Какие выводы мы можем из этого сделать? Ну сохранены инварианты, а значения-то какие будут у полей?

В том-то и дело, что конкретные значения неизвестны. И это сильно ограничивает практическое использование таких объектов. По сути единственное, что с ним можно гарантировано безопасно сделать - это разрушить.

И это главное. Вся магия с раскруткой стека и вызовом деструктором локальных объектов работает только если деструкторы вызываются безопасно. А для этого объект должен быть в валидном, но необязательно определенном, состоянии. То есть вы в принципе не можете восстановить работоспособность приложения, если ваши инструменты не предоставляют хотя бы базовую гарантию.

Здесь кстати можно провести параллель с мувнутыми объектами: ими тоже особо не попользуешься и по хорошему их надо просто удалить.

Примером предоставления только базовой гарантии может быть использование какой-нибудь базы данных. Если при выполнении запроса фреймворк выкинул исключение, например потому что соединение отвалилось, то объект для работы с базой остался в валидном состоянии, но нет никакой информации о том, выполнился запрос или нет:

auto db = std::make_shared<DBConnection>(credentials);
try {
auto result = db->Execute("UPDATE ...");
process(result);
} catch (std::exception& ex) {
std::cout << "We can cannot rely on table state and must retry with that in mind" << std::endl;
// retry
}


Поэтому мы должны иметь ввиду это неопределенное состояние коннекшена и базы при выполнении ретраев.

Provide guarantees. Stay cool.

#cppcore
  • 👍 14
  • ❤ 9
  • 🔥 4
  • 😁 3
  • 👎 2
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →