多线程同时拷贝 std::vector<> 引发的 内存越界 corrupted double-linked list

std::vector<YourClass> 即使YourClass是可平凡复制类型也回应发异常

引发异常的代码如下:

    SamplePointData &operator=(const SamplePointData &samplePointData) {

        if (this != &samplePointData) {
            this->channelData = samplePointData.channelData;
            this->openControlData = samplePointData.openControlData;
        }
        return *this;
    }

表现现象为在拷贝赋值函数中抛出Segment fault,或引发corrupted double-linked list

完整的struct代码如下(我使用了普通数组来替换他):

SampleData.h

//
// Created by HP on 2025/2/25.
//

#ifndef SSUDATACOMPUTEDRIVER_SAMPLEDATA_H
#define SSUDATACOMPUTEDRIVER_SAMPLEDATA_H

#include "ToolUtils/ByteContainer.h"
#include "PipeManager/InputSpscQueue.h"
#include "PublicClass/Properties.h"

class SampleData {


public:

    explicit SampleData() = default;

    /* 设备名称 Topic 值 */
    explicit SampleData(std::string value) {


        if (value.size() != 1230) {
            throw std::runtime_error("Input value is illegal.");
        }


        size_t offset{};

        /* 查看读入数据 */
        uint8_t array[value.size()];
        memcpy(array, value.c_str(), value.size());


        {
            FourByte fourByte;
            std::copy(array + offset, array + offset + 4l, fourByte.value_char);
            /* 时间戳 */
            timeStamp.store(fourByte);
            offset += FourByteStruct::getByteLength();
        }


        {
            FourByte fourByte;
            std::copy(array + offset, array + offset + 4l, fourByte.value_char);

            /* 同步有效性 */
            synchronizationValidity.store(fourByte);
            offset += FourByteStruct::getByteLength();
        }

        {
            TwoByte twoByte;
            std::copy(array + offset, array + offset + 2l, twoByte.value_char);

            /* 秒内帧序号 */
            frameNumberWithinOneSecond.store(twoByte);
            offset += TwoByteStruct::getByteLength();
        }


        /* 构造毫秒级时间戳 */
        timeStampMs =
                timeStamp.load().value_uint32_t  /* 秒转毫秒 */ +
                frameNumberWithinOneSecond.load().value_uint16_t * frameInterval; /* 帧序号*间隔即为时间偏移量 */

        {
            /* 帧内采样总数 */
            TwoByte twoByte;
            std::copy(array + offset,
                      array + offset + 2l, twoByte.value_char);
            totalSamplePointsWithinOneFrame.store(twoByte);


            offset += TwoByteStruct::getByteLength();
        }


        {
            /* 模拟量通道数 */
            OneByte oneByte;
            oneByte.value_char = array[offset];
            analogChannelsNumber.store(oneByte);

            offset += OneByteStruct::getByteLength();
        }

        {
            /* 开关量通道数 */
            OneByte oneByte;
            oneByte.value_char = array[offset];
            analogChannelsNumber.store(oneByte);

            offset += OneByteStruct::getByteLength();
        }


        /* 拆解采样值  */
        for (auto i = 0; i < totalSamplePointsWithinOneFrame.load().value_uint16_t; ++i) {

            OnePieceOfChannelData onePieceOfChannelData;  /* 缓冲通道数据 */

            /* 采样值 */
            for (auto j = 0; j < analogChannelsNumber.load().value_uint8_t; ++j) {


                auto string = value.substr(offset + j * TwoByteStruct::getByteLength(),
                                           TwoByteStruct::getByteLength());

                TwoByte twoByte;
                std::copy(string.begin(), string.end(), twoByte.value_char);

                onePieceOfChannelData.insertChannel(twoByte);
            }

            OnePieceOfOpenControlData onePieceOfOpenControlData;  /* 缓冲开入数据 */

            /* 处理开入值 */
            for (auto j = 0;
                 j < switchChannelsNumber.load().value_uint8_t >> 3l /* 单字节保存8个开入 故右移动3位 */; ++j) {


                onePieceOfOpenControlData.insertOpenControl(
                        OneByte{value.substr(j, OneByteStruct::getByteLength())[0]});
            }

            if (!onePieceOfChannelData.isFull()) {
                throw std::runtime_error("Sample point or open control data is lost.");
            }

            samplePointData[currentInputIndex] = std::move(
                    SamplePointData{onePieceOfChannelData, onePieceOfOpenControlData});
            currentInputIndex++;
        }

    };

    [[nodiscard]] auto getChannelNumber() const {
        return analogChannelsNumber.load().value_uint8_t;
    }

    [[nodiscard]] auto getTimeStamp() const {
        return timeStamp.load().value_uint32_t;
    }

    [[nodiscard]] auto getTimeStampMs() const {
        return timeStampMs;
    }

    [[nodiscard]] auto getFrameNumberWithinOneSecond() const {
        return frameNumberWithinOneSecond.load().value_uint16_t;
    }

    /* 被消费完毕 */
    bool isConsumed() {
        return currentInputIndex < samplePointDataNumber;
    }

    /* 获取当前的最新数据片 */
    auto getOnePieceOfData() {

        auto tmp = samplePointData[currentOutputIndex];
        currentOutputIndex++;
        return tmp;
    }

    [[nodiscard]] auto getSamplePointData() const {
        return samplePointData;
    }

    auto size() const {
        return currentInputIndex.load();
    }

    SampleData(const SampleData &sampleData) {
        currentInputIndex.store(sampleData.currentInputIndex);
        timeStampMs = sampleData.timeStampMs;
        timeStamp.store(sampleData.timeStamp);
        synchronizationValidity.store(sampleData.synchronizationValidity);
        frameNumberWithinOneSecond.store(sampleData.frameNumberWithinOneSecond);
        totalSamplePointsWithinOneFrame.store(sampleData.totalSamplePointsWithinOneFrame);
        analogChannelsNumber.store(sampleData.analogChannelsNumber);
        switchChannelsNumber.store(sampleData.switchChannelsNumber);
        currentInputIndex.store(sampleData.currentInputIndex);

        std::copy(sampleData.samplePointData, sampleData.samplePointData + samplePointDataNumber, samplePointData);

    }

    SampleData &operator=(const SampleData &sampleData) {

        if (this != &sampleData) {
            currentInputIndex.store(sampleData.currentInputIndex);
            timeStampMs = sampleData.timeStampMs;
            timeStamp.store(sampleData.timeStamp);
            synchronizationValidity.store(sampleData.synchronizationValidity);
            frameNumberWithinOneSecond.store(sampleData.frameNumberWithinOneSecond);
            totalSamplePointsWithinOneFrame.store(sampleData.totalSamplePointsWithinOneFrame);
            analogChannelsNumber.store(sampleData.analogChannelsNumber);
            switchChannelsNumber.store(sampleData.switchChannelsNumber);
            currentInputIndex.store(sampleData.currentInputIndex);

            std::copy(sampleData.samplePointData, sampleData.samplePointData + samplePointDataNumber, samplePointData);
        }

        return *this;
    }

    SampleData(SampleData &&sampleData) noexcept {
        currentInputIndex.store(sampleData.currentInputIndex);
        timeStampMs = sampleData.timeStampMs;
        timeStamp.store(sampleData.timeStamp);
        synchronizationValidity.store(sampleData.synchronizationValidity);
        frameNumberWithinOneSecond.store(sampleData.frameNumberWithinOneSecond);
        totalSamplePointsWithinOneFrame.store(sampleData.totalSamplePointsWithinOneFrame);
        analogChannelsNumber.store(sampleData.analogChannelsNumber);
        switchChannelsNumber.store(sampleData.switchChannelsNumber);
        currentInputIndex.store(sampleData.currentInputIndex);

        std::copy(sampleData.samplePointData, sampleData.samplePointData + samplePointDataNumber, samplePointData);
    }

    SampleData &operator=(SampleData &&sampleData) noexcept {
        if (&sampleData != this) {
            currentInputIndex.store(sampleData.currentInputIndex);
            timeStampMs = sampleData.timeStampMs;
            timeStamp.store(sampleData.timeStamp);
            synchronizationValidity.store(sampleData.synchronizationValidity);
            frameNumberWithinOneSecond.store(sampleData.frameNumberWithinOneSecond);
            totalSamplePointsWithinOneFrame.store(sampleData.totalSamplePointsWithinOneFrame);
            analogChannelsNumber.store(sampleData.analogChannelsNumber);
            switchChannelsNumber.store(sampleData.switchChannelsNumber);
            currentInputIndex.store(sampleData.currentInputIndex);

            std::copy(sampleData.samplePointData, sampleData.samplePointData + samplePointDataNumber, samplePointData);
        }
        return *this;
    }


    bool operator==(const SampleData &other) const {
        return timeStamp.load().value_uint32_t == other.timeStamp.load().value_int32_t &&
               synchronizationValidity.load().value_int32_t == other.synchronizationValidity.load().value_int32_t &&
               frameNumberWithinOneSecond.load().value_int16_t ==
               other.frameNumberWithinOneSecond.load().value_int16_t &&
               totalSamplePointsWithinOneFrame.load().value_int16_t ==
               other.totalSamplePointsWithinOneFrame.load().value_int16_t &&
               analogChannelsNumber.load().value_int8_t == other.analogChannelsNumber.load().value_int8_t &&
               switchChannelsNumber.load().value_int8_t == other.switchChannelsNumber.load().value_int8_t;
    }


private:

    std::atomic<uint64_t> currentOutputIndex{};        /* 当前被消费的数据下标 */

    constexpr static uint64_t frameInterval = 5l;   /* 每数据包的间隔 这里是1s内发送200包 因此每包的间隔是5ms */

    uint64_t timeStampMs{};       /* 毫秒级时间戳 */

    std::atomic<FourByte> timeStamp;                   /* 时间戳 */

    std::atomic<FourByte> synchronizationValidity;     /* 同步有效性 */

    std::atomic<TwoByte> frameNumberWithinOneSecond;   /* 秒内帧序号 */

    std::atomic<TwoByte> totalSamplePointsWithinOneFrame;  /* 帧内采样总点数 */

    std::atomic<OneByte> analogChannelsNumber;            /* 模拟量通道数 */

    std::atomic<OneByte> switchChannelsNumber;            /* 开关量通道数 */

    /* 帧内采样点数据 使用无所队列直接作为缓冲区 */

    constexpr static uint64_t samplePointDataNumber = 64l;

    std::atomic<uint64_t> currentInputIndex{};

    SamplePointData samplePointData[samplePointDataNumber]; /* 采样点数据初始化完毕后不进行修改 */

};

#endif //SSUDATACOMPUTEDRIVER_SAMPLEDATA_H


SamplePointData.h

/* 单位数据片 包含通道数据值和开入值 */
struct SamplePointData {

    explicit SamplePointData() = default;

    explicit SamplePointData(OnePieceOfChannelData channelData,
                             OnePieceOfOpenControlData openControlData) : channelData(channelData),
                                                                          openControlData(std::move(openControlData)) {}


    OnePieceOfChannelData channelData;
    OnePieceOfOpenControlData openControlData;

    // 拷贝构造函数
    SamplePointData(const SamplePointData &samplePointData) = default;

    // 拷贝赋值函数
    SamplePointData &operator=(const SamplePointData &samplePointData) {

        if (this != &samplePointData) {
            this->channelData = samplePointData.channelData;
            this->openControlData = samplePointData.openControlData;
        }
        return *this;
    }

    // 移动构造函数
    SamplePointData(SamplePointData &&samplePointData) noexcept
            : channelData(std::move(samplePointData.channelData)),
              openControlData(std::move(samplePointData.openControlData)) {
    }

    // 移动赋值运算符
    SamplePointData &operator=(SamplePointData &&samplePointData) noexcept {
        if (this != &samplePointData) {
            channelData = std::move(samplePointData.channelData);
            openControlData = std::move(samplePointData.openControlData);
        }
        return *this;
    }


};
posted @ 2025-04-23 15:25  BlackSnow  阅读(84)  评论(0)    收藏  举报