为何在std::unique_ptr中创建std::thread会触发线程析构崩溃?
崩溃根因定位
你看到的崩溃栈是完全可复现的标准C++线程生命周期异常,逐行对应触发逻辑:
- 最上层的
std::terminate()是崩溃的直接触发点:C++标准明确规定,如果std::thread对象在可连接(joinable)状态下被析构,程序会直接调用terminate终止运行,没有任何兼容逻辑或异常抛出。 - 下一层的
std::thread::~thread()就是这个触发terminate的析构函数本身。 - 最底层的
MultiChannelDiskRecordingWav::flush()就是导致析构执行的代码位置。
为什么unique_ptr持有的线程会被析构?
你在flush函数末尾的核心赋值逻辑是:
flushThread = std::make_unique<std::thread>(flush);
这行代码的实际执行顺序是:
- 在堆上创建一个新的
std::thread对象,生成指向它的临时unique_ptr - 释放unique_ptr内部之前持有的旧指针
- 将新的unique_ptr指针赋值给成员变量
关键就在第二步:如果上一次调用flush时创建的线程还没有被join或者detach,仍然处于joinable状态,那么这时候释放旧的thread对象,就会直接触发joinable析构对应的terminate逻辑。
整个崩溃流程和你贴的回溯栈完全匹配:
- 第一次调用flush,线程被创建放到unique_ptr里,没有做join/detach操作,后台开始执行刷盘逻辑
- 第二次调用flush,执行到赋值新unique_ptr的步骤,旧的线程对象被释放
- 旧线程还处于joinable状态,析构函数直接调用
std::terminate(),程序崩溃
代码里附带的其他致命隐患
就算解决了线程析构的问题,现有实现依然会随机出现崩溃或数据错乱:
- 缓冲区拷贝无同步:主线程循环把writeBuffer内容拷贝到tempWriteBuffer的时候,没有加任何锁。后台线程启动后会直接读取tempWriteBuffer构造写入用的vector,如果主线程还在写这个缓冲区,就会触发数据竞争,轻则写入文件内容错乱,重则访问非法内存崩溃。
- lambda捕获逻辑错误:你在lambda里构造写入用的floats数组时,用的是通过this指针访问的动态成员值
mWriteCursorFrames*mChannelCount,根本没用到你提前捕获的capturedWriteCursorFrames和capturedChannelCount。如果在后台线程开始执行前,这两个成员值被主线程修改,后台线程就会按照错误的长度读取tempWriteBuffer,直接越界访问。 - 生命周期无兜底:类对象被销毁的时候,如果flushThread里还持有没跑完的joinable线程,照样会触发同样的terminate崩溃。
修正参考
- 替换原来直接给unique_ptr赋值的逻辑,覆盖之前必须等旧线程执行完:
// 给成员变量赋新线程前,先处理旧线程 if (flushThread != nullptr && flushThread->joinable()) { flushThread->join(); } flushThread = std::make_unique<std::thread>(flush);
- 修正lambda的捕获逻辑,所有后台线程需要的缓冲区内容、长度值全部用值捕获传入,不要依赖动态的成员变量引用:
auto flush = [this, capturedWriteCursorFrames = mWriteCursorFrames, capturedChannelCount = mChannelCount, // 直接在主线程把需要写入的缓冲区拷贝成独立副本,后台线程读取时不会触发数据竞争 writeDataCopy = std::vector<float>(tempWriteBuffer, tempWriteBuffer + mWriteCursorFrames*mChannelCount)](){ std::lock_guard<std::mutex> lk{recordingFileMutex}; recordingFile.Write(writeDataCopy); bytesWritten += capturedWriteCursorFrames * capturedChannelCount * sizeof(float); };
- 在类的析构函数中增加兜底逻辑,确保销毁对象前所有正在运行的刷盘线程被join完成。
内容的提问来源于stack exchange,提问作者Poperton
相关产品推荐
相关产品推荐

