I am unsure if this is expected behavior in c++11. Here is an example of what I found.
#include <iostream>
#include <thread>
using namespace std;
class A {
public:
virtual void a() = 0;
thread t;
A() : t(&A::a, this) {}
virtual ~A() {
t.join();
}
};
class B : public A {
public:
virtual void a() {
cout << "B::a" << endl;
}
};
int main() {
B b;
this_thread::sleep_for(chrono::seconds(1));
}
When compiled and run
$ g++ -std=c++11 -pthread test.cpp -o test
$ ./test
B::a
$
But when the sleep is removed...
int main() {
B b;
//this_thread::sleep_for(chrono::seconds(1));
}
something strange happens
$ g++ -std=c++11 -pthread test.cpp -o test
$ ./test
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
$
Could this be a bug?
You can use std::promise/std::future as a simpler alternative to a bool / condition_variable / mutex in this case. A future is not susceptible to spurious wakes and doesn't require a mutex for synchronisation. Save this answer.
C++ language does not provide a sleep function of its own. However, the operating system's specific files like unistd. h for Linux and Windows. h for Windows provide this functionality.
std::thread Threads allow multiple functions to execute concurrently. std::thread objects may also be in the state that does not represent any thread (after default construction, move from, detach, or join), and a thread of execution may not be associated with any thread objects (after detach).
When in constructor and destructor virtual
functions behave differently. In A
s constructor B
has not initialised yet, this is why B
s virtual function cannot possibly be called yet. See virtual
:
When a virtual function is called directly or indirectly from a constructor or from a destructor (including during the construction or destruction of the class’s non-static data members, e.g. in a member initializer list), and the object to which the call applies is the object under construction or destruction, the function called is the final overrider in the constructor’s or destructor’s class and not one overriding it in a more-derived class. In other words, during construction or destruction, the more-derived classes do not exist.
So, that member function pointer &A::a
gets resolved in that other thread when it calls it. This call resolution uses the virtual table because &A::a
is a pointer to a virtual member function. The first thing that a constructor does is it sets the virtual table pointer to the virtual table of the class. If B
s constructor has been entered by the time (this->&A::a)()
is called, then it calls B::a
. There is a race condition between that new thread invoking (this->&A::a)()
and the current thread executing A
and B
constructors.
A great article on starting threads from the constructor
https://rafalcieslak.wordpress.com/2014/05/16/c11-stdthreads-managed-by-a-designated-class/
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