在处理低级字节操作时reinterpret_cast是错误的
Is reinterpret_cast bad when dealing with low-level byte manipulation?
我正在编写一个websocket服务器,我必须处理我需要取消掩码的掩码数据。
掩码是unsigned char[4],数据也是unsigned char* buffer。
我不想一个字节一个字节地进行异或,我宁愿一次对4个字节进行异或。
uint32_t * const end = reinterpret_cast<uint32_t *>(data_+length);
for(uint32_t *i = reinterpret_cast<uint32_t *>(data_); i != end; ++i) {
*i ^= mask_;
}
在这种情况下使用reinterpret_cast有什么问题吗?
另一种方法是下面的代码,它不那么清晰,也不那么快:
uint64_t j = 0;
uint8_t *end = data_+length;
for(uint8_t *i = data_; i != end; ++i,++j) {
*i ^= mask_[j % 4];
}
我洗耳恭听各种替代方案,包括依赖于c++11特性的方案。
这个方法有几个潜在的问题:
- 在某些系统中,大于
char
类型的对象需要正确对齐才能访问。uint32_t
的一个典型要求是对象与一个能被4整除的地址对齐。 - 如果
length / sizeof(uint32_t) != 0
,循环可能永远不会终止。 - 根据系统的端到端不同,
mask
需要包含不同的值。如果mask
是由一个合适的数组的*reinterpret_cast<uint32_t>(char_mask)
产生的,那么它就不应该是一个数组。
如果这些问题都得到了解决,reinterpret_cast<...>(...)
可以在您所拥有的情况下使用。重新解释指针的含义是这个操作存在的原因之一,有时是需要的。我将创建一个合适的测试用例来验证它是否正常工作,以避免在将代码移植到不同的平台时不得不寻找问题。
我个人会采用不同的方法,直到分析显示它太慢:
char* it(data);
if (4 < length) {
for (char* end(data + length - 4); it < end; it += 4) {
it[0] ^= mask_[0];
it[1] ^= mask_[1];
it[2] ^= mask_[2];
it[3] ^= mask_[3];
}
}
it != data + length && *it++ ^= mask_[0];
it != data + length && *it++ ^= mask_[1];
it != data + length && *it++ ^= mask_[2];
it != data + length && *it++ ^= mask_[3];
我确实在软件中使用了许多类似的方法,这些方法意味着更快,并且没有发现它们是一个明显的性能问题。
在这种情况下,reinterpret_cast
没有什么特别的问题。但是,保重。
32位循环是不正确的,因为它不能满足负载不是32位大小的倍数的情况。我想有两种可能的解决方案:
- 将for循环检查中的
!=
替换为<
(人们使用<
是有原因的,并不是因为他们愚蠢……)并按字节顺序执行后面的1-3个字节 - 安排缓冲区,使有效负载部分的缓冲区大小为32位的倍数,并且仅对额外的字节进行异或。(大概代码在向调用者返回字节时检查有效负载长度,所以这无关紧要。)
此外,根据代码的结构,您可能还必须处理某些cpu的不对齐数据访问。如果在32位对齐的缓冲区中缓冲了整个帧,包括报头和所有内容,并且有效载荷长度为<126字节或>65,535字节,则屏蔽键和有效载荷都将不对齐。
不管它的价值是什么,我的服务器使用类似于第一个循环的东西:
for(int i=0;i<n;++i)
payload[i]^=key[i&3];
与32位选项不同,这基本上不可能出错。
相关文章:
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 错误:"cast"未命名类型void setCastDescription(std::string
- C++:"Expected '(' for function-style cast or type construction"错误
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- static_cast会丢弃错误,但C风格的演员cast有效
- 禁用 Clang 中的"cast from pointer to smaller type uint32_t"错误
- 错误 C2440: 'type cast':无法从 'bool' 转换为 'CString'
- "Expected '(' for function-style cast or type construction"错误是什么意思?
- <function-style-cast> 错误:无法从'initializer list'转换为'std::thread'
- 编译错误:C/ c++中cast void *失败
- dynamic-cast-c++dynamic_cast错误处理