提问人:Maga 提问时间:10/27/2023 最后编辑:Mr FoozMaga 更新时间:10/27/2023 访问量:97
将 std::unique_ptr<uint8_t[]> 转换为结构unique_ptr而不丢失 uint8_t[] 缓冲区
Casting std::unique_ptr<uint8_t[]> to struct unique_ptr without losing uint8_t[] buffer
问:
有没有办法将 to 转换为,以便结构指向与原来的地址相同的地址并保存该缓冲区?std::unique_ptr<uint8_t[]>(n)
std::unique_ptr</*some_struct*/>
uint8_t ptr
auto buffer = std::make_unique<uint8_t[]>(100);
std::unique_ptr<dummy> header = std::move(buffer); // error
struct dummy // string data
{
uint64_t unk1; // 0x0
uint64_t string_offset; // 0x8
uint32_t c59d1c81; // 0x10
uint16_t byte_length; // 0x14
uint16_t string_length; // 0x16
uint64_t unk2; // 0x18
uint8_t* get_string() { return (uint8_t*)(uint64_t(this) + 0x8 + string_offset); }
};
在此示例中,buffer 保存结构的字节。但是,它还包含一个字符串,该字符串可通过成员和方法获取。0x20
dummy
string_offset
get_string
答:
3赞
Jarod42
10/27/2023
#1
忽略可能的锯齿/对齐问题,您可能会这样做
auto buffer = std::make_unique<uint8_t[]>(100);
std::unique_ptr<dummy, Deleter> header(reinterpret_cast<dummy*>(buffer.release()));
跟
struct Deleter
{
void operator()(dummy* p) const {
p->~dummy(); // Noop in your case
delete[] reinterpret_cast<uint8*>(p);
}
};
评论
0赞
zzz
10/27/2023
与 Deleter unique_ptr的绝佳解决方案。但是对于基元类型 (POD),删除 uint* 与删除 void* 相同,与删除 dummy* 相同,不是吗?我相信这是在实践中,但不确定是否有任何违反标准的行为。
0赞
Jarod42
10/27/2023
@zzz:删除是UB(就像“不完整”类型一样)。删除 uint* 与删除 dummy* 不同(的类型应与 的类型匹配)(即使在实践中它可能会起作用)。Violation 用于严格的别名和生存期(虚拟生存期当前从不开始),但与 无关。void*
void
delete
new
std::unique_ptr
0赞
Maga
10/27/2023
@PatrickRoberts 出色的自定义删除器解决方案,谢谢!我将研究 delete[] 运算符如何与 uint8_t* 强制转换配合使用,但至少它现在有效。顺便说一句,它应该在标头初始化中是reinterpret_cast<dummy*>。
0赞
Maga
10/27/2023
@Jarod42 对不起,给你贴错了标签。再次感谢!
0赞
zzz
10/30/2023
@Jarod42 真的。我的意思是“任何原始类型”而不是“void”。
评论
new[]
new
std::unique_ptr
struct
uint8_t
unique_ptr
unique_ptr
unique_ptr
unique_ptr
union