多线程同时拷贝 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;
}
};

浙公网安备 33010602011771号