I stumbled upon what I think is a very easy way to unknowingly shoot yourself in the foot.
first a little introduction
The initialization order of data members is the order of declaration of the data members. So this is illegal:
struct A
{
std::size_t i_;
std::size_t length_;
A(std::size_t length)
: i_{length_} // UB here. `length_` is uninitialized
length_{length}
{}
};
Because data member length_
is uninitialized when used in the initializer of i_
. Fortunately both gcc
and clang
give a very nice warning for this. The simple solution is to initialize each data members from the parameters, i.e. i_{length}
.
now to the main point
But how about when it is not immediately obvious. E.g. when a data member is a std::thread
struct X
{
std::thread thread_;
std::mutex mutex_;
X() : thread_{&X::worker_thread, this}
{}
auto worker_thread() -> void
{
// use mutex_
std::lock_guard lk{mutex_}; // boom?
// ..
}
};
The same situation arises when using data member initializer:
struct X
{
std::thread thread_{&X::worker_thread, this};
std::mutex mutex_;
};
This looks very innocent and neither gcc
and clang
warn on this scenario. This is not surprising, as the dependency is hidden.
I would immagine the above scenario is not uncommon so I am looking on confirmation that this is indeed UB. And declare the std::mutex
data member last, or default initialize it and assign it later.
Yes, it is indeed undefined behavior. As a matter of fact, you have over-complicated the example with threads and mutexes. Every time you are using this
in initialization of members (explicitly or implicitly), you are opening yourself to troubles. Easier example:
struct A {
int y;
int x = 0;
A() : y(sety()) { }
int sety() { return x; } // Ka-boom!
};
It is always quite dangerous to call non-static member functions from within member initialization; and one generally has also to be careful when calling member functions from constructor body.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With