C++实现定时器运行报terminate without an active exception如何解决?
C++定时器崩溃原因与优化方案
崩溃原因
你遇到的报错直接来自std::thread的析构规则:
- 当std::thread对象处于*可联接(joinable)*状态(即线程还在运行、没有调用过
join()或detach())时,对象析构会自动调用std::terminate()终止程序。你代码中start函数里的std::thread t是局部变量,函数执行完立刻析构,此时子线程还在sleep处于joinable状态,直接触发崩溃。 - 代码还有隐藏的未定义行为:lambda用引用捕获了
start函数的局部参数sec和f,start函数退出后这两个变量被销毁,子线程访问的是野引用,就算解决了thread析构问题后续也会出现异常。 - 缺少必要头文件:
sleep函数需要包含<unistd.h>,printf需要包含<stdio.h>。
高灵活性定时器设计建议
- 线程生命周期管理:将std::thread作为类成员变量存储,对外提供
join、detach接口,或者在确认安全的前提下手动调用detach让线程后台独立运行;lambda捕获参数优先用值拷贝,避免野引用问题。 - 通用回调支持:不要限制为裸函数指针,改用
std::function<void()>作为回调类型,可兼容普通函数、lambda表达式、类成员函数、std::bind包装的可调用对象,适配更多场景。 - 任务取消支持:新增
std::atomic<bool>类型的停止标记,子线程执行前先判断标记,不需要执行时可以提前退出,也方便程序退出时安全回收线程资源。 - 多任务高效调度:如果需要同时管理多个定时任务,不要每个任务单独开线程,改用单调度线程+优先级队列的设计:按任务触发时间排序任务列表,用条件变量等待最近任务的触发时间,到点执行对应回调,线程资源利用率更高。
- 周期性任务支持:新增重复执行间隔参数,单次任务执行完成后重新计算下一次触发时间,再插回任务队列即可实现周期性定时功能。
改进后的基础定时器示例代码
#include <thread> #include <functional> #include <atomic> #include <cstdio> #include <unistd.h> class Timer { public: using Callback = std::function<void()>; void start(int sec, Callback f, bool repeat = false) { m_stop = false; m_thread = std::thread([this, sec, f, repeat]() { do { sleep(sec); if (m_stop) break; f(); } while(repeat && !m_stop); }); } void stop() { m_stop = true; if (m_thread.joinable()) { m_thread.join(); } } ~Timer() { stop(); } private: std::thread m_thread; std::atomic<bool> m_stop{false}; }; void test() { printf("here called\n"); } int main() { Timer t; // 单次执行任务 t.start(3, test); // 也可传入lambda等其他可调用对象 // t.start(2, [](){ printf("lambda callback called\n"); }); sleep(5); // 模拟主进程其他工作逻辑 t.stop(); return 0; }
内容的提问来源于stack exchange,提问作者nick
相关产品推荐
相关产品推荐

