Failure handling with destructors vs. catch (...) { fix(); throw; } - c++

Let's say I'm doing something that requires cleanup when an exception is thrown.
For example, say I'm creating a dynamic array, and I need to construct objects, but their constructors may throw an exception:
size_t const n = 100;
T *const p = static_cast<T *>(operator new(sizeof(T) * n));
size_t i;
for (i = 0; i < n; ++i)
new (&p[i]) T(1, 2, 3); // Not exception-safe if T::T(T const &) throws!
I can fix it either via catch (...) { ...; throw; }:
size_t const n = 100;
T *const p = static_cast<T *>(operator new(sizeof(T) * n));
size_t i;
try
{
for (i = 0; i < n; ++i)
new (&p[i]) T(1, 2, 3);
}
catch (...)
{
while (i > 0)
p[--i].~T();
operator delete(p);
throw;
}
or via a scoped destructor:
size_t n = 100;
struct Guard
{
T *p;
size_t i;
Guard(size_t n) : i(), p(static_cast<T *>(operator new(sizeof(T) * n))) { }
~Guard()
{
while (i > 0)
p[--i].~T();
operator delete(p);
}
} guard(n);
for (guard.i = 0; guard.i < n; ++guard.i)
new (&guard.p[guard.i]) T(1, 2, 3);
guard.i = 0; // Successful... "commit" the changes
guard.p = NULL; // or whatever is necessary to commit the changes
Which technique should I prefer to use when, and why?
(Note: This example is only meant to show the difference between two techniques. I know it's not perfect code, so please do not focus on this particular example. It's just for illustration.)

The solution with destructor is better than the explicit try/catch:
it is reusable, if you will need to do similar initialisation in another function, you can just reuse the same guard class
it is easier to maintain - let's say that in some situation your function needs to return with failure but no exception is thrown. With the guard class it is handled more or less automatically
it is cleaner, since the code is more modular

In general, I would say it is a matter of scaling and safety.
The problem with try/catch is two-fold:
safety issue: any early return that ignores the catch (somehow) fails to cleanup
scaling issue: nested try/catch blocks make a mess of the code
scoping issue: to be accessible in the catch the variable must be defined before the try and thus supports default-construction/nullability; it can be painful
Instead, Deferred Statements and Guards do not create unnecessary blocks/scopes and thus no indentation, and read linearly.
Example:
char buffer1[sizeof(T)];
try {
new (buffer1) T(original);
char buffer2[sizeof(T)];
try {
new (buffer2) T(original);
// stuff here
} catch(...) {
reinterpret_cast<T*>(buffer2)->~T();
throw;
}
} catch(...) {
reinterpret_cast<T*>(buffer1)->~T();
throw;
}
Compared to:
char buffer1[sizeof(T)];
new (buffer1) T(original);
Defer const defer1{[&buffer1]() { reinterpret_cast<T*>(buffer1)->~T(); } };
char buffer2[sizeof(T)];
new (buffer2) T(original);
Defer const defer1{[&buffer2]() { reinterpret_cast<T*>(buffer2)->~T(); } };
// stuff here
I would note that it seems a good idea to generalize those:
class Guard {
public:
explicit Guard(std::function<void()> f): _function(std::move(f)) {}
Guard(Guard&&) = delete;
Guard& operator=(Guard&&) = delete;
Guard(Guard const&) = delete;
Guard& operator=(Guard const&) = delete;
~Guard() {
if (not _function) { return; }
try { _function(); } catch(...) {}
}
void cancel() { _function = std::function<void()>{}; }
private:
std::function<void()> _function;
}; // class Guard
class Defer {
public:
explicit Defer(std::function<void()> f): _guard(std::move(f)) {}
private:
Guard _guard;
}; // class Defer

Related

C++ how to call D'tor?

I wrote:
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) { // allocation failed for one node (Doesn't throw any exception)
~UnLabeledList();
delete[] SegArray;
throw;
}
SegArray[i] = NOT_INIT;
}
};
};
In case one allocation failed I want to destroy the object (since it has previously allocated nodes) for example when allocation fails at i==5. How can I call the d'tor of UnLabeledListto prevent memory leak?
You should never call a destructor yourself to clean up things. The language rules take care of it.
It is recommended to use standard classes like std::vector and std::list rather than raw arrays/pointers and homebrew lists. The standard classes already take care of exceptions and cleanup, so your class should look something like
class image {
public:
std::list<std::pair<int, int>> UnLabeledList;
std::vector<int> SegArray;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(Segments, NOT_INIT), TotalSegments(Segments) {
for (int i = 0; i < Segments; ++i) {
UnLabeledList.push_back({i, NOT_INIT});
}
};
};
You can't directly invoke the destructor of the UnLabeledList member like that.
If the image constructor throws an uncaught exception, the UnLabeledList member will be destructed automatically, if it was successfully constructed before the exception was thrown.
The correct solution is to implement a clear() method in the linked_list class, which you can call whenever needed, including in the copy constructor and destructor. For example:
template<...>
class linked_list {
// ...
public:
linked_list() {
// initialize the list as needed...
}
linked_list(const linked_list &src) : linked_list() {
for (each node in src) {
if (!push_back(...)) {
clear();
throw ...;
}
}
}
~linked_list() {
clear();
}
linked_list& operator=(const linked_list &rhs) {
// clear and copy the list as needed...
}
void clear() {
// free nodes as needed...
}
node* push_back(...) {
// add new node as needed...
return ...; // nullptr on error
}
//...
};
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw ...; // <-- UnLabeledList::~linked_list() called automatically!
}
SegArray[i] = NOT_INIT;
}
~image() {
delete[] SegArray;
} // <-- UnLabeledList::~linked_list() called automatically!
};
You also can't call a parameter-less throw; outside of an active catch handler. Outside of a catch, you must throw an actual value/object explicitly.
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw std::runtime_error("can't push a new node");
}

How to create pool of contiguous memory of non-POD type?

I have a scenario where I have multiple operations represented in the following way:
struct Op {
virtual void Run() = 0;
};
struct FooOp : public Op {
const std::vector<char> v;
const std::string s;
FooOp(const std::vector<char> &v, const std::string &s) : v(v), s(s) {}
void Run() { std::cout << "FooOp::Run" << '\n'; }
};
// (...)
My application works in several passes. In each pass, I want to create many of these operations and at the end of the pass I can discard them all at the same time. So I would like to preallocate some chunk of memory for these operations and allocate new operations from this memory. I came up with the following code:
class FooPool {
public:
FooPool(int size) {
foo_pool = new char[size * sizeof(FooOp)]; // what about FooOp alignment?
cur = 0;
}
~FooPool() { delete foo_pool; }
FooOp *New(const std::vector<char> &v, const std::string &s) {
return new (reinterpret_cast<FooOp*>(foo_pool) + cur) FooOp(v,s);
}
void Release() {
for (int i = 0; i < cur; ++i) {
(reinterpret_cast<FooOp*>(foo_pool)+i)->~FooOp();
}
cur = 0;
}
private:
char *foo_pool;
int cur;
};
This seems to work, but I'm pretty sure I need to take care somehow of the alignment of FooOp. Moreover, I'm not even sure this approach is viable since the operations are not PODs.
Is my approach flawed? (most likely)
What's a better way of doing this?
Is there a way to reclaim the existing memory using unique_ptrs?
Thanks!
I think this code will have similar performance characteristics without requiring you to mess around with placement new and aligned storage:
class FooPool {
public:
FooPool(int size) {
pool.reserve(size);
}
FooOp* New(const std::vector<char>& v, const std::string& s) {
pool.emplace_back(v, s); // in c++17: return pool.emplace_back etc. etc.
return &pool.back();
}
void Release() {
pool.clear();
}
private:
std::vector<FooOp> pool;
}
The key idea here being that your FooPool is essentially doing what std::vector does.

Initializing object which throws exceptions

I have class A, which has constructor A(string filepath)
class A {
public:
A(string filePath);
private:
A();
}
I need to initialize A, and use it later. Constructor A throws exceptions.
int main() {
A a;
try {
a = A("./my/file/path");
} catch (exception e) {
return 1;
}
// Use a
return 0;
}
What would be the most elegant solution? (I dont want to have something like init function, because it makes it possible to have empty A object.)
The most elegant solution is probably to move all your logic which uses a into a function
int use_a(A &a);
int main() {
try {
A a("./my/file/path");
// if we reach here, no exception was thrown
// hence a is safe to use
return use_a(a);
} catch (exception e) {
// if we reach here a never really existed
return 1;
}
}
You're correct to prefer avoiding two-phase initialization - this way use_a can implicitly rely on a being safe to use.
The most elegant solution is:
int main() {
try {
A a("...");
// use a
} catch (const std::exception& e) {
// log e
return 1;
}
return 0;
}
If you don't want empty A objects consider deleting the default constructor. Note that this makes using some stl containers more difficult, while ensuring no invalid object exists.
In addition to that i think using throw in constructors very much allowed. If you don't want to do that consider the noexcept keyword. Note that throws in destructors can cause problems and are usually avoided.
As alternative, you might turn the exception in "optional/checkable" construction with std::optional or std::unique_ptr:
std::optional<A> MakeA(const std::filesystem::path& path)
{
try {
return A{path};
} catch (std::exception& e) {
return std::nullopt;
}
}
int main() {
auto a = MakeA("./my/file/path");
if (!a) {
return 1;
}
// Use *a
return 0;
}

c++: Try catch on construction of a class with a const member

Consider the following class:
class MyClass
{
private:
const unsigned int num;//num identifies the object. needs to be const
unsigned int checkNum(unsigned int);// verifies that num has a valid value
public:
MyClass(unsigned int n): num(checkNum(n)) {}
};
unsigned int MyClass:checkNum(unsigned int n)
{
if (some_condition)
throw std::invalid_argument("Invalid number");
return n;
}
The difficulty is that the object must be constructed inside a try block because of the range check:
int main()
{
try {
MyClass mc(1000);
}
catch (std::invalid_argument &ia)
{
std::cout << ia.what();
}
return 0;
}
The problem is that mc is then not available outside of the try block.
Possible solutions:
Extend the try block over the whole scope where mc is used. Not practical in many cases.
Don't throw the exception in the constructor, but throwing it afterwards would be too late.
The only acceptable solution I can think of is to use smart pointers to bring the declaration outside of the try block:
int main()
{
std::unique_ptr<MyClass> my_class_ptr;
try {
my_class_ptr = std::make_unique<MyClass>(1000);
}
catch (std::invalid_argument &ia)
{
std::cout << ia.what();
}
return 0;
}
Are there any other/better solutions?
What do you intend to do with mc when its construction was deemed invalid, and "cancelled" via exception?
Having the try extend around the entire scope of the object makes perfect sense.
mc shouldn't be accessible outside of the try block.
In your point 1, "not practical in many cases" is simply false.
A try block is the solution where you want to handle failure.
An alternative is to not handle it.
In other news, in your point 2, "Don't make MyClass::num const. Not good , it supposed to be non-mutable for the duration of the object." is very questionable. It is to some extent subject to personal opinion, but technically there's no problem. Also, there's no connection between the const and the range checking: that hypothesized connection simply does not exist.
You should validate the ID number before constructing the mc object with it. Don't do the validation inside the constructor itself:
class MyClass
{
private:
const unsigned int num;
public:
MyClass(unsigned int n): num(n) {}
};
unsigned int checkNum(unsigned int n)
{
if (some_condition)
throw std::invalid_argument("Invalid number");
return n;
}
int main()
{
unsigned int num;
try {
num = checkNum(some_input);
}
catch (std::invalid_argument &ia)
{
std::cout << ia.what();
return -1;
}
MyClass mc(num);
return 0;
}
You can use a function-try-block to prevent any wished of using mc outside of the try block. : >
int main() try{
return 0;
} catch(...) {
}

Call a function before function exits

I will begin with an example. Suppose I need to guard a code with a function inside a mutex. There are two ways of implementing this.
#include <iostream>
#include <vector>
#include <pthread.h>
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
std::vector<float> myVec;
void threadfunc(int i, float value)
{
pthread_mutex_lock(&myMutex);
if(i <= 0 || i > myVec.size())
{
pthread_mutex_unlock(&myMutex);
return;
}
if(value < 0)
{
pthread_mutex_unlock(&myMutex);
return;
}
myVec[i] += value;
pthread_mutex_unlock(&myMutex);
return;
}
class AUTOMUTEX
{
private:
pthread_mutex_t *mMutex;
public:
AUTOMUTEX(pthread_mutex_t *mutex): mMutex(mutex)
{
pthread_mutex_lock(mMutex);
}
~AUTOMUTEX()
{
pthread_mutex_unlock(mMutex);
}
};
void threadfunc_autolock(int i, float value)
{
AUTOMUTEX autoMutex(&myMutex);
if(i <= 0 || i > myVec.size())
{
return;
}
if(value < 0)
{
return;
}
myVec[i] += value;
return;
}
int main()
{
threadfunc_autolock(5, 10);
threadfunc(0, 7);
return 1;
}
As it is clear from the example threadfunc autolock is better implementation as calling pthread_mutex_unlock function return is taken care by destructor call to AUTOMUTEX (C++ 11 thread has support for this. So we don't need our own implementation of AUTOMUTEX if we are using C++11 thread library).
Is there a way we can achieve this without implementing a wrapper class each time we need to do this with some set/reset function pair. Does boost or C++ 11 have some predefined template class with which we can achieve the behaviour of AUTOMUTEX for any such "set/reset" sort of function. This is really helpful for functions with multiple points of return.
In other words does boost/C++ provide a class with the following behaviour.
//sample code not compilable.
template <class T, class Y>
class myAuto
{
myAuto()
{
T();
}
~myAuto()
{
Y();
};
You may write your own geneirc RAII class, something like:
class Finally
{
public:
explicit Finally(std::function<void()> f) : mF(f) {}
~Finally() noexcept() {
try
{
mF();
} catch (...) {
// Handle error.
}
}
Finally(const Finally&) = delete;
Finally(Finally&&) = delete;
Finally& operator=(const Finally&) = delete;
Finally& operator=(Finally&&) = delete;
private:
std::function<void()> mF;
};
Usage:
{
pthread_mutex_lock(&myMutex);
Finally finally([&](){ pthread_mutex_unlock(&myMutex); });
//..
}
Even if a dedicated RAII object may be more appropriate in some case (as Mutex).
There is a proposal for a generic scope guard to be included in the next C++ standard, and I think it is accepted. You can find an implementation here, together with a link to the reference paper.
In principle, it is similar to the classical ScopeGuard, but it also provides some special cases e.g. for C-like file APIs.
You could use something like ScopeGuard. (Now somewhat old-fashioned.)
But given how easy and clear it is to construct a specific RAII wrapper for each resource type I would normally do that.
(I don't think boost ever adopted anything like ScopeGuard. With std::function, lambdas and so on it's easy to do your own.)
What's wrong with writing your own generic resource wrapper?
template <typename Res, typename Fn = std::function<void(Res*)>>
class resource_mgr
{
Res* resource;
Fn initialize, finalize;
public:
resource_mgr (Res* r, Fn i, Fn f)
: resource(r),
initialize(i),
finalize(f)
{
initialize(resource);
}
resource_mgr (resource_mgr const&) = delete;
resource_mgr (resource_mgr&&) = delete;
resource_mgr const& operator = (resource_mgr const&) = delete;
resource_mgr const& operator = (resource_mgr&&) = delete;
~resource_mgr
{
try
{
finalize(resource);
}
catch(...)
{
std::cerr << "Uh-oh!"
}
}
};
You can keep it simple or go wild on something like this -- use smart pointers, define move operations, add support for custom error handlers, etc. You might use it like this:
void threadfunc_autolock(int i, float value)
{
resource_mgr<mutex_t> autoMutex (
&myMutex,
[](auto* p) { if (!pthread_mutex_lock(p)) throw Something(); },
[](auto* p) { if (!pthread_mutex_unlock(p)) throw Something(); }
);
/* . . . */
}
Here's an example using Boost.ScopeExit (untested):
#include <boost/scope_exit.hpp>
...
void threadfunc_autolock(int i, float value)
{
pthread_mutex_lock(&myMutex);
BOOST_SCOPE_EXIT(&myMutex) {
pthread_mutex_unlock(&myMutex);
} BOOST_SCOPE_EXIT_END
if(i <= 0 || i > myVec.size())
{
return;
}
if(value < 0)
{
return;
}
myVec[i] += value;
}