You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 18:20:34