June 12, 2020

Thread Destruction with Join

The strategy of thread ending (with a join for instance) is primordial for your multithreaded program.

​Sometimes, on ​​aged programs with large history, I​ had seen threads without join or/and any kind of destruction strategy.

A thread without any destruction strategy is extremely dangerous and can trigger issues that are painful to analyze! The consequences of threads without join are easy to ​show, let see this simple code:

#include <iostream>
#include <thread>

void threadFunction()
{
    std::cout << "(THREAD) Hey, I am thread!" << std::endl;
}

int main()
{
    std::cout << "(THREAD) Hey, I am main!" << std::endl;
    std::thread threadCreated(threadFunction);
    return 0;
}

​Let see ​the output...

(THREAD) Hey, I am main!
(THREAD) Hey, I am thread!
terminate called without an active exception
Aborted (core dumped)

​Here my application crashed. Why?

The response is ​that we exited the program before that "threadFunction" finished. A simple join added resolve this issue:

#include <iostream>
#include <thread>

void threadFunction()
{
    std::cout << "(THREAD) Hey, I am thread!" << std::endl;
}

int main()
{
    std::cout << "(THREAD) Hey, I am main!" << std::endl;
    std::thread threadCreated(threadFunction);
    threadCreated.join();
    return 0;
}
(THREAD) Hey, I am main!
(THREAD) Hey, I am thread!

​Here the main function waits for the thread termination before to exit the program. Now I am exiting properly my program.

​Be careful


​I want to keep your attention here. In this example, the consequences ​was easy to analyze and not dramatic.


Now, let's imagine this kind of issue in a large program. Imagine that a super class generates a thread.

What happens if this class is destroyed without join on the concerned thread?


There is an undefined behavior ​(in the best case, a crash during testing).

​A thread not correctly managed can, in the long term, trigger those kind of ​behaviors:

​Example of risks ​if a thread is not correctly exited

1.

​Nothing special, the thread exit ​by himself. However, if the design is not review, this case is dangerous and can ​evolve to the 2nd or worst, the 3rd case.

2.

​Crash... During the test, this is the best case for me. it is ideal to apply an action to this thread and review the design.

3.

​Memory modification, corruption... The worst one: Vicious, extremely dangerous and hard to detect.

​During my carrier, I already ​saw ​the third case:

A crash (fortunately) occurred in the program, nothing special on the line when the crash happens. So, we started to analyze and debug the code. This ​​debug ​took an entire week.

Finally, it was a detached thread which manipulated object supposed to be destroyed.

​The resolution ​of those kind of issue are not easy to apply(Risk of deadlock, bad memory manipulation...). Fortunately, after few tentative, the risk of deadlock was limited and the bug had been fixed!

​Always mastery your thread ​design

​This last section is a simple message:

​Always mastery your threads

​A thread without any strategy of initialization and destruction can have terrible consequences on long term.


  • A thread creation should not be done without design ​specification.
  • A single thread application design​ is not always compatible for multithreading.
  • A thread not correctly designed can manipulate destroyed objects.

A thread should always be destroyed properly. With or without join, it should​ be correctly designed to avoid surprises.

​The multithreading is a ​wonderful tool, thanks to this, your application can be really reactive!

However, as I featured here, the question of multithreading in C++ ​should be taken with great caution..

​In any kind of project, we should ​always ​be able to predict the threads behavior, in any cases and any states.

I hope that I ​​​was not too "judgmental" during this post. You certainly already apply those principles in your project.

About the author 

Axel Fortun

​Developer specialized in Linux environment and embedded systems.
​Knowledge in multiple languages as C/C++, Java, Python​ and AngularJs.
​Working as Software developer since 2014 with a beginning in the car industry​ and then in ​medical systems.