使用 boost 库检查 CRC 没有给出令人满意的结果

Checking CRC using boost library does not give satisfactory result

我正在使用 boost crc 库来计算 112 位(80 位数据 + 32 位 crc)位集的 32 位 crc。为了测试,我将所有 80 个数据位重置为 0。crc 的计算似乎工作正常,但是当我将计算的 crc 附加到数据并再次计算 crc 时,我得到一个值 > 0。但我期待一个 crc值恰好为 0。这是代码:

    // creating 112-bit bitset and reset all values to 0
    bitset<112> b_data;
    b_data.reset();

    // create string containing data and blank crc
    string crc_string = b_data.to_string<char,string::traits_type,string::allocator_type>();

    // calculating crc using boost library
    boost::crc_32_type crc32;
    crc32 = for_each(crc_string.begin(), crc_string.end(), crc32);
    bitset<32> b_crc(crc32());

    // writing calculated crc to the last 32-bit of the 112-bit bitset.
    for(int i = 0; i!= b_crc.size(); i++){
        b_data[i+80] = b_crc[i];
    }

    // create string containing data and calculated crc
    string crc_string_check = b_data.to_string<char,string::traits_type,string::allocator_type>();

    // calculate crc again to check if the data is correct
    boost::crc_32_type crc32_check;
    crc32_check = std::for_each(crc_string_check.begin(), crc_string_check.end(), crc32_check);

    // output the result
    cout << crc32() << endl;
    cout << crc32_check() << endl;

输出为:

    1326744236
    559431208

我预期的输出是:

    1326744236
    0

所以出了点问题,但是什么?有什么想法吗?

提前致谢。

首先,正如评论者所说,一旦检查和,就不要包括 CRC 位。我建议创建一个辅助函数来检查 n 位(在本例中为 80)。

其次,考虑重构代码以使其具有可读性和表达意图:

Live On Coliru

#include <iostream>
#include <string>
#include <bitset>
#include <algorithm>
#include <boost/crc.hpp>
#include <cassert>

template <size_t N>
uint32_t crc32_n(std::bitset<N> const& bs, size_t n) {
    assert(n <= N);

    std::string const s = bs.template to_string<char>();
    auto f = s.begin();

    return std::for_each(f, f+n, boost::crc_32_type{})();
}

int main() {
    std::bitset<112> b_data;

    // set some random data (above the first 32 bits that are for CRC)
    srand(time(0));
    b_data.set(rand()%80 + 32);

    auto const crc = crc32_n(b_data, 80);

    std::cout << crc                 << ":\t" << b_data << "\n";
    b_data |= crc;
    std::cout << crc32_n(b_data, 80) << ":\t" << b_data << "\n";
}

打印例如

1770803766: 0000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000
1770803766: 0000000000000000000000000000000000000000000000000000000000000000000000010000000001101001100011000101001000110110

或(在另一个 运行)

2436181323: 0000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000
2436181323: 0000000000000000000000000000000000000000000000000000000000000000000000100000000010010001001101010010110101001011

我很想继续并删除可怕的 to_string 电话,但看到 How do I convert bitset to array of bytes/uint8?

如果您要将 CRC 包含在 CRC 校验中(我认为这是正确的技术),则预期结果始终为零。不是传输的 CRC。

您对 "satisfactory" 的期望不正确。只有当 CRC 具有零初始化且没有异或结果时,它才会具有您期望的 属性 。但是,您请求的标准 CRC-32 crc_32_type 使用 0xffffffff 初始化 CRC 寄存器,并使用 0xffffffff.

异或结果

但是,当您将消息的 CRC 与消息的 CRC 连接在一起时,您将始终获得相同的常量(假设您对 CRC 的字节进行了正确排序)。对于这个特定的 CRC,该常量是 0x2144df1c,并且是四个零字节的 CRC。

以这种方式定义 CRC 很常见,因此一串零的 CRC 不为零。由于初始化和异或相同,所以空集的CRC方便地为零。

您应该做的只是计算没有 CRC 的消息的 CRC,并将其与传输的 CRC 进行比较。这是通常所做的,并且通常适用于所有消息哈希。