C++17创建线程触发SIGABRT问题求助
问题分析与解决
你的代码在创建第二个线程时触发SIGABRT,核心原因大概率是按值传递大容器导致内存分配失败,或是线程构造时的参数传递问题,以下是具体分析和修复方案:
1. 核心问题:容器按值传递引发的异常
你在创建线程时直接传递lines容器,std::thread会将参数复制到线程内部存储。如果lines是一个大容量容器,复制过程会消耗大量内存,触发std::bad_alloc异常;若未捕获该异常,程序会调用std::terminate(),最终触发SIGABRT信号。
而主线程调用时正常,是因为你可能直接传递了容器的引用,避免了复制开销。
2. 修复方案
(1)用std::ref传递容器引用
修改线程创建代码,通过std::ref传递lines的引用,避免不必要的容器复制:
auto p = Parser(.7); int tMax = thread::hardware_concurrency(); if (tMax == 0) tMax = 1; // 处理硬件并发数无法获取的情况 vector<thread> threads; int chunk = lines.size() / tMax; int remainder = lines.size() % tMax; for (int i = 0; i < tMax; ++i) { int start = chunk * i + min(i, remainder); // 最后一个线程处理剩余元素 int end = start + chunk + (i < remainder ? 1 : 0); // 用std::ref传递lines的引用 threads.emplace_back(&Parser::parse, &p, std::ref(lines), start, i); } // 必须等待所有线程完成 for (auto& t : threads) { if (t.joinable()) { t.join(); } }
(2)修正chunk范围计算
原代码中未处理lines.size()无法被tMax整除的情况,会导致部分元素被遗漏。上述修复代码中通过remainder变量分配剩余元素给前N个线程,确保所有元素都被处理。
(3)处理hardware_concurrency()返回0的情况
部分环境下thread::hardware_concurrency()会返回0(无法获取CPU核心数),此时需要默认设置线程数为1,避免除零错误。
3. 其他注意事项
- 必须join/detach线程:若主线程在子线程未完成时退出,会触发SIGABRT。上述代码中加入了
join()等待所有线程执行完毕。 - 互斥量的正确使用:确保
Parser::parse中对共享资源的访问通过互斥量正确同步,避免数据竞争。
内容的提问来源于stack exchange,提问作者Voxeldoodle
相关产品推荐
相关产品推荐

