# C++: terminate called without an active exception — std::thread destroyed while joinable

**Code:** `terminate called without an active exception` · **Category:** C/C++ · **Seen on:** C/C++, GCC, Clang

A `std::thread` object was destroyed (or reassigned) while its thread was still running, so the C++ runtime called `std::terminate`.

## Meaning

Every `std::thread` must be either joined or detached before its destructor runs. Exiting `main`, returning early, or an exception unwinding past a live thread object all trigger it. Use `std::jthread` (C++20), which joins automatically, or wrap threads in an RAII guard.

## Common causes

- `join()` or `detach()` never called on a thread
- Early return or exception skipping the `join()`
- Assigning a new thread to a variable that still owns a running thread
- Thread stored in a container that is destroyed before the threads end

## Quick fix

1. Call `t.join()` (or `t.detach()` if truly independent) before the thread object dies
2. Use `std::jthread` in C++20
3. Use an RAII wrapper so join happens even on exceptions

## Detailed fix by platform

### C++

1. `std::jthread worker([]{ /* work */ });` joins in its destructor
2. For older standards write a small guard class whose destructor calls `if (t.joinable()) t.join();`

## Code examples

### Always join

```cpp
#include <thread>
#include <iostream>

int main() {
    std::thread t([] { std::cout << "working\n"; });
    // forgot t.join();   -> terminate called without an active exception
    t.join();             // fix (or use std::jthread in C++20)
}
```

## How to diagnose

1. **Join** — Is every thread joined or detached on all paths?
2. **Exceptions** — Can an exception skip the join?
3. **Ownership** — Is a thread variable overwritten?

---
Source: [WhatIsMyError](https://whatismyerror.com/errors/cpp/terminate-without-active-exception)
