C++多线程抛出std::system_error异常及计时逻辑错误求助
问题根因
1. 程序崩溃原因
你的std::thread向量threads每次循环都会追加新线程对象,但循环结束后没有清空,下一轮循环会继续往向量中新增内容,导致后续对已经执行过join、处于终止状态的线程对象重复执行join操作,触发std::system_error抛出Invalid argument错误。
另外你通过new创建的Chronometer对象从未执行delete释放,存在严重内存泄漏。
2. 计时速度翻倍原因
你所有线程都在修改同一个传入的全局chrono对象,没有做互斥保护,多个线程同时修改同一个变量属于数据竞争,自然会出现计数速度翻倍的异常情况。同时你的start_chrono方法存在逻辑错误:if(sec > 59)这里读取的是当前实例的sec成员,不是传入的参数chrono的sec成员,逻辑本身就不成立。
修复方案
- 每次循环结束后清空
threads和car_crono向量,释放堆内存,避免重复操作已终止的线程对象 - 不需要额外传入
chrono参数,直接操作当前Chronometer实例的成员变量即可,每个线程对应一个独立的Chronometer实例,就不会出现互相干扰的问题 - 多线程输出内容需要加互斥锁,避免多个线程输出内容乱码
- 修正
start_chrono的逻辑,不要混用当前对象和参数对象的成员
修复后代码示例
main.cpp
#include <stdio.h> #include <time.h> #include <iostream> #include <cstdlib> #include <unistd.h> #include <sstream> #include <thread> #include <vector> #include "mychrono.hpp" int main() { while (1) { std::vector<Chronometer*> car_crono; std::vector<std::thread> threads; for(int i = 0; i < 2; i++) { car_crono.push_back(new Chronometer); } for(int i = 0; i<2; i++) { threads.push_back(std::thread(&Chronometer::start_chrono, car_crono[i])); } for (auto &th : threads) { th.join(); } // 释放堆内存 for (auto p : car_crono) { delete p; } std::cout << "Hello-world" << std::endl; } }
chrono.cpp
#include "mychrono.hpp" #include <time.h> #include <iostream> #include <cstdlib> #include <unistd.h> #include <sstream> #include <thread> #include <mutex> // 互斥锁保护cout输出 static std::mutex cout_mtx; Chronometer::Chronometer() : hour(0), min(0), sec(0) { } void Chronometer::start_chrono() { bool condition = true; while(condition) { sleep(1); sec++; if(sec > 59) { min++; sec = 0; } if(min > 59) { hour++; sec = 0; min = 0; } if(sec == 10) { condition = false; } std::lock_guard<std::mutex> lock(cout_mtx); std::cout << "chrono: " << *this << std::endl; } }
mychrono.hpp
#include <time.h> #include <iostream> #include <sstream> #ifndef mychrono_hpp #define mychrono_hpp class Chronometer { private: int hour, min, sec; public: Chronometer(); void start_chrono(); Chronometer& finish_chrono(Chronometer& chrono); friend std::ostream& operator<<(std::ostream& flux, Chronometer t); Chronometer& operator=(const Chronometer& other); ~Chronometer(); }; #endif
内容的提问来源于stack exchange,提问作者Thib
相关产品推荐
相关产品推荐

