【发布时间】:2014-11-12 01:15:12
【问题描述】:
我有一个处理 char[] 缓冲区以发送/接收消息的程序。到目前为止,它是这样处理的:
#pramga pack(1)
struct messageType
{
uint8_t data0:4;
uint8_t data1:4;
uint8_t data2;
//etc...
};
#pragma pack()
void MyClass::processMessage(char* buf)
{
// I already know buf is big enough to hold a messageType
messageType* msg = reinterpret_cast<messageType*>(buf);
//populate class member variables
m_data0 = msg->data0;
m_data1 = msg->data1;
m_data2 = msg->data2;
//etc
}
现在从我从阅读中收集到的信息是,由于严格的别名,这在技术上是未定义的行为,应该使用 memcpy 代替吗?我不太明白的是,将buf逐字节复制到messageType msgNotPtr,然后从msgNotPtr读取,实际上会避免什么潜在问题?
关于发送,而不是这样做:
void MyClass::sendMessage()
{
char buf[max_tx_size];
messageType* msg = reinterpret_cast<messageType*>(buf);
msg->data0 = m_data0;
//etc...
send(buf);
}
我读到我应该使用placement new istead,ala:
messageType* msg = new(buf) messageType;
如果我这样做,我是否需要添加额外的清理,因为结构 messageType 仅包含 POD 类型(例如手动触发析构函数)?
编辑:现在我想一想,sendMessage 仍然未定义吗?我是否还需要将最后一个命令替换为 send(reinterpret_cast<char*>(msg)) 之类的内容,以确保编译器不会优化调用?
【问题讨论】:
-
鉴于您提供的代码,我想说您不需要手动调用析构函数,因为
buf是在堆栈上分配的。您正在处理 POD,因此调用析构函数的唯一原因是释放分配的内存,而这里不需要。 -
@bialpio 与缓冲区是否在堆栈上无关。不知道在POD中使用placement new时是否需要调用析构函数。
-
在 POD 的情况下,没有理由调用析构函数 - 没有什么要清理的(例如:没有要关闭的句柄,没有指向空闲的指针等),内存将是函数返回时释放,因为它是在堆栈上分配的。另一方面:
char * buf = new char[sizeof(messageType)];需要释放内存,我希望调用析构函数会释放它。 -
@bialpio 在这种情况下,你会使用
delete[] buf,不是吗?我认为这不会改变手动调用析构函数的任何内容。
标签: c++