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

多线程环境下向std::vector添加数据偶发异常问题咨询

问题根因排查

你代码的崩溃和类地址差异无关,核心是以下几个实现错误:

  • lambda捕获悬垂指针(直接触发崩溃的核心原因)
    for循环中clsDP是循环内局部变量,你创建线程时用了引用捕获[&],第一次循环结束进入第二次循环时,clsDP变量本身的内存会被复用覆盖,两个线程运行时访问的clsDP大概率是无效地址或者指向同一个第二次创建的DataProcess实例,访问成员变量m_vecData自然触发异常。
  • 未初始化DataStorage的存储容量
    你从来没有调用过SetDataVectorSize给DataStorage的内部vector分配空间,后续DataInsertLoop直接给vecData[idx]赋值会触发数组越界。
  • DataInsertLoop逻辑错误
    函数入参的start和end没有被正确使用,循环条件写死成idx < _v1->size(),如果start不为0会直接导致写vecData越界。
  • rand()非线程安全
    C++标准库的rand()实现没有线程安全保证,多线程并发调用会触发未定义行为。
  • 线程任务参数重复
    两个线程的DataProcess都配置了start=0, end=halfdata,完全没有实现分片处理的逻辑,第二个线程的计算结果直接覆盖第一个的结果。
方案合理性说明

为每份分片数据创建独立DataProcess实例处理的方案本身没有问题,是多线程数据处理的常用实现,修复上述BUG即可正常运行。

修复后的核心代码示例
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <random>

using namespace std;

static std::mutex m;

class DataStorage
{
private: 
    std::vector<long long> vecData;
public:
    DataStorage() = default;
    ~DataStorage() = default;
    void SetDataVectorSize(int size)
    {
        vecData.clear();
        vecData.resize(size);
    }
     
    void DataInsertLoop(const std::vector<long long>& _v1, long long start)
    {
        std::lock_guard<std::mutex> lock(m); // 用RAII锁避免异常时死锁
        for (long long idx = 0; idx < _v1.size(); ++idx)
        {
            vecData[start + idx] = _v1[idx];
        }
    }
};

class DataProcess
{
private:
    long long m_startIndex;
    long long m_endIndex;
    DataStorage* m_mainStorage;
    std::vector<long long> m_vecData;
    std::mt19937 rng; // 线程安全的随机数生成器

public:
    DataProcess(long long startindex, long long endindex, unsigned int seed)
        : m_startIndex(startindex), m_endIndex(endindex),
        m_mainStorage(nullptr), rng(seed)
    {
       m_vecData.reserve(endindex - startindex); // 预分配空间避免频繁扩容
    }
    ~DataProcess() = default;
    void SetMainAdrr(DataStorage* mainstorage)
    {
        m_mainStorage = mainstorage;
    }
    void DataRun()
    {
        long long num = 0;
        for (long long idx = m_startIndex; idx < m_endIndex; ++idx)
        {
            num += rng();
            m_vecData.push_back(num);
        }
        m_mainStorage->DataInsertLoop(m_vecData, m_startIndex);
    }
};

int main()
{
    clock_t beginTime, endTime;
    DataStorage* mainStorage = new DataStorage();
    const long long totalcount = 200000000;
    mainStorage->SetDataVectorSize(totalcount); // 先初始化存储容量
    const long long halfdata = totalcount / 2;
    std::thread t1,t2;
    std::random_device rd;

    for (int t = 0; t < 2; ++t)
    {
        long long start = t * halfdata;
        long long end = (t == 1) ? totalcount : halfdata;
        DataProcess* clsDP = new DataProcess(start, end, rd());
        clsDP->SetMainAdrr(mainStorage);
        // 值捕获clsDP,避免悬垂指针
        if (t == 0)
        {
            t1 = std::thread([clsDP]() {
                clsDP->DataRun();
                delete clsDP; // 用完释放内存
            });
        }
        else
        {
            t2 = std::thread([clsDP]() {
                clsDP->DataRun();
                delete clsDP;
            });
        }
    }

    t1.join();
    t2.join();

    endTime = clock();
    double resultTime = (double)(endTime - beginTime);
    std::cout << "Multi Thread " << resultTime / 1000 << " sec" << std::endl;
    printf("--------------------\n");
    getchar();
    delete mainStorage;
    return 0;
}

内容的提问来源于stack exchange,提问作者JasonMin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:39:02