c++ - 除了 memcpy,bit_cast 还会有哪些额外的 UB(如果有的话)?
问题描述
我有一个类,其目的是将可能具有对齐限制的数据移入或移出数据未对齐的序列化内存缓冲区。我已按如下方式设置和获取处理程序:
#include <cstring>
template<typename T>
struct handle_type {
static inline T get(const void *data) {
T value;
memcpy(&value, data, sizeof(T));
return value;
}
static inline void set(void *data, T value) {
memcpy(data, &value, sizeof(T));
}
};
c++20出来后,我希望它会变成下面这样:
#include <bit>
template<typename T>
struct handle_type {
union unaligned { char bytes[sizeof(T)]; }; // EDIT: changed from struct
static inline T get(const void *data) {
return std::bit_cast<T>(*(const unaligned*)data);
}
static inline void set(void *data, T value) {
*(unaligned *)data = std::bit_cast<unaligned>(value);
}
};
它会起作用吗?或者我使用的是 inerim 类型,未对齐的结构类型,是否容易造成问题?
解决方案
get
除非用户提供了指向unaligned
对象的指针,否则您的函数是 UB。你的set
函数同样是 UB,除非data
是一个unaligned
对象。这些情况中的任何一种都违反了严格的别名。请记住:严格的别名后门是关于实际的char*
;这与恰好包含char*
.
此外,set
可能是编译错误,完全取决于 的实现是否unaligned
与T
. 毕竟,unaligned
最后可能有填充。
bit_cast
希望主要处理对象,而不是随机的内存缓冲区。为此,您应该坚持使用memcpy
.
<改为使用
union
而不是struct
>
那没有任何改变;使用 aunion
并不能保证 的大小union
等于其最大数据成员的大小。来自 [class.union]/2:
联合的大小足以包含其最大的非静态数据成员。
重点补充:“足够”,而不是“等于”。该标准允许实现使联合大于其最大数据成员的能力,因为这样的大小仍然是“足够的”。
推荐阅读
- csv - 从 CSV 中提取列并将它们放入字典的方法
- javascript - 在javascript中一段时间内运行setInterval()的问题?
- c# - 为什么 Id 返回 null 而不是从数据库中返回下一个 Id?
- haskell - Haskell - 如何泛化 Float 和 Double
- r - 在 data.table 中使用唯一但跟踪原始行(例如唯一然后匹配)
- javascript - 无法在 JavaScript 中的可变长度参数数组上运行函数
- excel - 为什么我的单元格值在循环新工作簿时会堆积起来
- amazon-web-services - AWS 格林格拉斯。无法从本地网络中的设备 mqtt 客户端触发核心的 lambda 函数
- javascript - 每张幻灯片的实时间隔修改
- git - 在本地分支 A 上显示本地分支 B 没有的提交