我在这里坐了几个小时,看代码,只是不明白。
关于std :: vector canData,它用作缓冲区来解码和编码来自CAN DBC解析器的数据。
我的问题的完整示例是here.

基本上,有一个值编码到数组,然后再从该数组解码。但是此数组的大小始终为零,即使清除该数组后,尽管其值为零,仍然可以从其中解码数据。

有人可以向我解释一下吗?
我想念什么吗?

unsigned int canIdentifier = 0x100;
std::vector<std::uint8_t> canData;
canData.reserve(4);
network.messages[canIdentifier].signals["multiplexor"].encode(canData, 0);
network.messages[canIdentifier].signals["signal_1"].encode(canData, 0x12);

std::cout << "size: " << canData.size() << std::endl;

canData.clear();
decodeMessage(canIdentifier, canData);
std::cout << "2size: " << canData.size() << std::endl;


更新了所需功能:

uint64_t Signal::decode(std::vector<uint8_t> & data)
{
/* safety check */
if (bitSize == 0) {
    return 0;
}

/* copy bits */
uint64_t retVal = 0;
if (byteOrder == ByteOrder::BigEndian) {
    /* start with MSB */
    unsigned int srcBit = startBit;
    unsigned int dstBit = bitSize - 1;
    for (unsigned int i = 0; i < bitSize; ++i) {
        /* copy bit */
        if (data[srcBit / 8] & (1 << (srcBit % 8))) {
            retVal |= (1ULL << dstBit);
        }

        /* calculate next position */
        if ((srcBit % 8) == 0) {
            srcBit += 15;
        } else {
            --srcBit;
        }
        --dstBit;
    }
} else {
    /* start with LSB */
    unsigned int srcBit = startBit;
    unsigned int dstBit = 0;
    for (unsigned int i = 0; i < bitSize; ++i) {
        /* copy bit */
        if (data[srcBit / 8] & (1 << (srcBit % 8))) {
            retVal |= (1ULL << dstBit);
        }

        /* calculate next position */
        ++srcBit;
        ++dstBit;
    }
}

/* if signed, then fill all bits above MSB with 1 */
if (valueType == ValueType::Signed) {
    if (retVal & (1 << (bitSize - 1))) {
        for (unsigned int i = bitSize; i < 8 * sizeof(retVal); ++i) {
            retVal |= (1ULL << i);
        }
    }
}

return retVal;
}

void Signal::encode(std::vector<uint8_t> & data, uint64_t rawValue)
{
/* safety check */
if (bitSize == 0) {
    return;
}

/* copy bits */
if (byteOrder == ByteOrder::BigEndian) {
    /* start with MSB */
    unsigned int srcBit = startBit;
    unsigned int dstBit = bitSize - 1;
    for (unsigned int i = 0; i < bitSize; ++i) {
        /* copy bit */
        if (rawValue & (1ULL << dstBit)) {
            data[srcBit / 8] |= (1 << (srcBit % 8));
        } else {
            data[srcBit / 8] &= ~(1 << (srcBit % 8));
        }

        /* calculate next position */
        if ((srcBit % 8) == 0) {
            srcBit += 15;
        } else {
            --srcBit;
        }
        --dstBit;
    }
} else {
    /* start with LSB */
    unsigned int srcBit = startBit;
    unsigned int dstBit = 0;
    for (unsigned int i = 0; i < bitSize; ++i) {
        /* copy bit */
        if (rawValue & (1ULL << dstBit)) {
            data[srcBit / 8] |= (1 << (srcBit % 8));
        } else {
            data[srcBit / 8] &= ~(1 << (srcBit % 8));
        }

        /* calculate next position */
        ++srcBit;
        ++dstBit;
    }
}
}

最佳答案

逐步查看代码:

canData.reserve(4);


为可以包含(至少)4个uint8_t但包含0的向量分配内存(canData.resize(4)将更改向量大小)。然后,canData.capacity()为4(或更大),但是canData.size()为0。

使用操作符[]进行encode(...)方法访问向量。它不检查index是否在范围内(因此小于canData.size()),因此没有异常(如果使用向量at()而是抛出向量)。同样,由于访问的索引位于分配的内存中,因此在那里没有发生任何不良事件(特别是内存泄漏)。

canData.clear()


销毁所有在范围内的矢量元素,因此在索引0和canData.size()之间。因此,它不会碰到canData.size()上方的元素,在这种情况下为0。 clear()也不会缩小为矢量分配的内存(或不能保证重新分配给缩小的内存)-rink_to_fit()会这样做。

最后,decodeMessage在分配并填充了未破坏的正确数据的内存上运行。同样,使用vector operator []不会导致异常/内存泄漏。

如评论中所述,许多未定义的行为。

关于c++ - 从 vector 写入/读取的奇怪行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47463668/

10-11 05:57