使用 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)。
其次,考虑重构代码以使其具有可读性和表达意图:
#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 进行比较。这是通常所做的,并且通常适用于所有消息哈希。
我正在使用 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)。
其次,考虑重构代码以使其具有可读性和表达意图:
#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 进行比较。这是通常所做的,并且通常适用于所有消息哈希。