我正在编写这个从远程服务器接收包的C ++代码。由于包的大小事先是未知的,因此代码首先接收8个字节,它告诉整个包的大小。然后它分配一个足够大的缓冲区并将整个包接收到缓冲区中。
我的问题是从const char*
转换为uint64_t*
部分:是否可以安全地转换指针,然后将内容读作uint64_t
?如果buf
未与8个字节对齐怎么办?
const char* buf;
RecvBytes(buf, sizeof(uint64_t)); // the first 8 bytes should tell us the size of the whole package
uint64_t pkg_size = *(uint64_t*)buf; // is this safe??
const char* pkg = new char[pkg_size];
RecvBytes(pkg, pkg_size);
答案 0 :(得分:2)
嗯,一般情况下,这应该没问题,但在一种情况下,可能有效,具体取决于发件人传递的实际参数的类型。
换句话说,如果发件人正在发送指向uint64_t
类型的指针,只有在这种情况下,代码才可以接受。
引用C11
,章节§6.3.2.3
指向对象类型的指针可以转换为指向不同对象类型的指针。如果 结果指针未正确对齐68)对于引用的类型,行为是 未定义。否则,当再次转换回来时,结果应该等于 原始指针。
答案 1 :(得分:0)
一般情况下,只有将(pauseOnDotsHover: false,
respondTo: 'window',
responsive: null,
rtl: true,
slide: '',
slidesToShow: 1,
slidesToScroll: 1,
speed: 500,
)const
强制转换为类型才是安全的,如果指针是从该类型获取然后再转换为char *
。
所以这里的防弹方式是:
char *
答案 2 :(得分:0)
我正在编写这个从远程服务器接收包的C ++代码。由于包的大小事先是未知的,因此代码首先接收8个字节,它告诉整个包的大小。然后它分配一个足够大的缓冲区并将整个包接收到缓冲区中。
我认为在包交换的上下文中,你不应该动态地分配一些东西,或者至少不是没有最大大小。 (并在必要时循环计算所有数据)
我会在你的情况下做这样的事情:
union {
uint64_t size;
char bytes[sizeof size];
} tmp;
RecvBytes(tmp.bytes, sizeof tmp.bytes);
if (tmp.size > SIZE_MAX) {
// bad
}
size_t size = static_cast<size_t>(tmp.size); // or use tmp.size
char data[MAX]; // or use something more object
for (size_t i = 0; i < size; i += MAX) {
RecvBytes(data, min(size - i, MAX));
// compute data
}
答案 3 :(得分:0)
我的问题是从const char *到uint64_t * part的转换:是否可以安全地转换指针,然后将内容读取为uint64_t?
一般情况下,它不安全且为undefined behavior,因此您应该scared。例如,您的代码可能会在PowerPC计算机上崩溃,其中指向uint64_t
的指针应与8个字节对齐(否则,在解除引用时,可能会出现SIGBUS
或SIGSEGV
错位指针)。
如果buf没有与8个字节对齐怎么办?
在x86处理器上,您可以使用它们:允许取消引用未对齐的指针,但是效率低(因此您应该避免这样做)。
动态分配的指针(由malloc
或::operator new
获得)保证足够对齐,因此new char[x]
的结果可以安全地转换为uint64_t*