【发布时间】:2018-05-02 20:20:36
【问题描述】:
我正在寻找一种方法来使用 unique_ptr 来分配一个结构,该结构包含一个 char 数组,其字节数动态设置以支持不同类型的消息。
假设:
struct MyMessage
{
uint32_t id;
uint32_t data_size;
char data[4];
};
如何将下面的 send_message() 转换为使用智能指针?
void send_message(void* data, const size_t data_size)
{
const auto message_size = sizeof(MyMessage) - 4 + data_size;
const auto msg = reinterpret_cast<MyMessage*>(new char[message_size]);
msg->id = 3;
msg->data_size = data_size;
memcpy(msg->data, data, data_size);
// Sending the message
// ...
delete[] msg;
}
我尝试使用以下代码使用智能点无法编译:
const auto message_size = sizeof(MyMessage) - 4 + data_size; const auto msg = std::unique_ptr<MyMessage*>(new char[message_size]);
下面是一个完整的工作示例:
#include <iostream>
#include <iterator>
#include <memory>
using namespace std;
struct MyMessage
{
uint32_t id;
uint32_t data_size;
char data[4];
};
void send_message(void* data, const size_t data_size)
{
const auto message_size = sizeof(MyMessage) - 4 + data_size;
const auto msg = reinterpret_cast<MyMessage*>(new char[message_size]);
if (msg == nullptr)
{
throw std::domain_error("Not enough memory to allocate space for the message to sent");
}
msg->id = 3;
msg->data_size = data_size;
memcpy(msg->data, data, data_size);
// Sending the message
// ...
delete[] msg;
}
struct MyData
{
int page_id;
char point_name[8];
};
void main()
{
try
{
MyData data{};
data.page_id = 7;
strcpy_s(data.point_name, sizeof(data.point_name), "ab332");
send_message(&data, sizeof(data));
}
catch (std::exception& e)
{
std::cout << "Error: " << e.what() << std::endl;
}
}
【问题讨论】:
-
您的代码原样包含未定义的行为,如果它有效,那么您很幸运(实际上很不幸,因为您认为它还可以)。
const auto msg = reinterpret_cast<MyMessage*>(new char[message_size]);违反了严格的别名,memcpy(msg->data, data, data_size);超出了数组data的范围,对于任何data_size > 4。 -
这种技术在我们公司被广泛使用,我想如果你再看一遍你可能会看到 msg->data 指向一个由 new char[message_size] 分配的内存的偏移量。它可能看起来有数组的界限,但该数组确实正在访问内存中包含相关大小的位置。你觉得这有意义吗?
-
@LessWhite 不幸的是,即使它被一家不会使该代码合法 C++ 的公司广泛使用
-
它看起来有点明智,但整个事情(主要是原始帖子)和解决方案感觉像是过度工程,以将 C 和 C++ 想法整合到一个地方。为什么不使用字符串?是因为它们在某些线程中使用吗?我想我在这里错过了重点。
-
哎呀,记错了规则。指针比较将在单个分配中起作用,但指针算术不会(即使指向同一个完整对象的其他部分也不能跨越成员边界)
标签: c++ c++11 smart-pointers flexible-array-member