C++ - std::thread crashes upon execution
Destroying a std::thread
object associated with a joinable()
thread causes std::terminate()
to be called. §30.3.1.3 [thread.thread.destr]:
~thread();
If
joinable()
, callsstd::terminate()
. Otherwise, has no
effects. [ Note: Either implicitly detaching or joining ajoinable()
thread in its destructor could result in difficult to debug
correctness (for detach) or performance (for join) bugs encountered
only when an exception is raised. Thus the programmer must ensure that
the destructor is never executed while the thread is still joinable.
—end note ]
There are a multitude of possible fixes:
- Allocate the thread on the heap and having your function return a smart pointer to the thread object
- Or have it return a
std::thread
(moveserverConnect
into the return value) - Move
serverConnect
into something that won't be destroyed whenconnectToServer()
returns (e.g., a global variable) join()
the thread before you returndetach()
the thread before you return
The correct choice depends on your particular use case.
Code crashes when creating new thread c++
Functions are already passed around as pointers, use thread t(f)
instead of thread t(&f)
.
Moreover, since your main()
neither lasts longer than the thread or calls a t.join()
, the program will end before the thread finishes it's code, so that might be another reason for a crash. In fact it is probably the reason for the crash.
If you want "insta log"
to print instantly, then call t.join()
at the end of main()
. t.join()
will wait for the thread t
to end before continuing.
Thread crashing when trying to join
You cannot call join from the function which is the body of execution thread. It will give you the error:
Reference
Error Conditions :
resource_deadlock_would_occur if this->get_id() ==
std::this_thread::get_id() (deadlock detected)
you need to add additional method for instance
void Timer::stop() {
slaveTimer.join();
}
and call this method from thread which created timer1
instance
Timer timer1(10, [](){ std::cout << "Hello World" << std::endl; });
timer1.stop();
or join thread in dtor of Timer:
Timer::~Timer() {
slaveTimer.join();
}
Does std::thread in another thread crash if its parameters are deleted?
From this std::thread::detach
reference:
Separates the thread of execution from the thread object, allowing execution to continue independently. Any allocated resources will be freed once the thread exits.
[Emphasis mine]
Among those "allocated resources" will be the arguments, which means you can still safely use the arguments in the detached thread.
Unless you of course the arguments are references or pointers to objects that are destructed independently of the detached thread or the thread that created the detached thread.
Why a multithreading C++ program crashes if we don't use join(), while a similar Java program doesn't
It's rather simple: In contrast to C++, which terminates once main
has finished, a java program ends only if all (non-deamon) threads (including main) have finished (cf., for example, this oracle thread documentation):
When a Java Virtual Machine starts up, there is usually a single
non-daemon thread (which typically calls the method named main of some
designated class). The Java Virtual Machine continues to execute
threads until either of the following occurs:a. The exit method of class Runtime has been called and the security
manager has permitted the exit operation to take place.b. All threads that are not daemon threads have died, either by
returning from the call to the run method or by throwing an exception
that propagates beyond the run method.
C++, in contrast, will start destructing objects with static storage duration, and if a detached thread is still running and accessing such objects, this yields undefined behaviour (cf., for example, this C++ standard draft concerning program termination):
3.6.3 Termination
Destructors ([class.dtor]) for initialized objects (that is, objects
whose lifetime ([basic.life]) has begun) with static storage duration
are called as a result of returning from main and as a result of
calling std::exit ([support.start.term]).
c++, member thread object causes crash on structure deletion when it's running
trying to join the thread on the destructor just causes the thing to spit a resource deadlock exception which I don't understand since it's not trying to join itself it's trying to join a member object
delaydKick_ = std::thread([p = this](){
std::this_thread::sleep_for(std::chrono::seconds(3));
p->kick(); //calls the function from the player object defined above
});
Here p->kick()
is executed while still in the thread. So if you delete your player in p->kick()
, and call join()
in the destructor, you're trying to have the thread join itself.
You probably have an event loop in your application, which processes events like socket messages.
What you could do is:
delaydKick_ = std::thread([p = this](){
std::this_thread::sleep_for(std::chrono::seconds(3));
some_thread_safe_queue.push(this)
});
// ...
// In your application's event loop:
while (1) {
// ...
while (some_thread_safe_queue.size > 0) {
auto to_kick = some_thread_safe_queue.pop();
to_kick->kick();
}
}
You can check also co_await
and co_async
which would do really well to handle your problem.
Why does this simple threaded C++ program crash upon exit unless I call thread.join()?
According to cppreference on thread class destructor :
~thread()
: Destroys the thread object. If*this
still has an associated running thread (i.e.joinable() == true
),std::terminate()
is called.
And joinable()
:
[...] A thread that has finished executing code, but has not yet been joined is still considered an active thread of execution and is therefore joinable.
So you have to call join()
explicitely before your thread variable is automatically destroyed or use the detach()
member function.
Related Topics
How to Implement a Map with Different Data Types as Values
Borderless Window with Drop Shadow
Variable or Field Declared Void
Move Out Element of Std Priority_Queue in C++11
Conflict Between Copy Constructor and Forwarding Constructor
Why Implicit Conversion Is Harmful in C++
C++ Static_Cast Runtime Overhead
How to Use C++14 Features When Building Qmake Projects
Why "Not All Control Paths Return a Value" Is Warning and Not an Error
Auto' as a Template Argument Placeholder for a Function Parameter
Is It Safe to Reinterpret_Cast an Enum Class Variable to a Reference of the Underlying Type
How to Get a Non-Const C String Back from a C++ String
Undefined Symbol on a Template Operator Overloading Function