提问人:alf02 提问时间:11/17/2023 最后编辑:alf02 更新时间:11/19/2023 访问量:150
使用 malloc 创建等效于 struct 的内存块
Using malloc to create a chunk of memory equivalent to struct
问:
我想使用 malloc 创建一个与结构等效的内存块,如下面的代码所示,但我收到警告“C6378 'pMyStructByMalloc' 可能是 '0'”,似乎无法让它工作。
struct MyStruct
{
int a = 1;
std::string s = "test";
int b = 2;
};
MyStruct* pMyStruct = new MyStruct();
int a = 1;
int b = 2;
std::string s = "test";
int memorySize = sizeof(int) + sizeof(std::string) + sizeof(int);
char* pMyStructByMalloc = (char*)malloc(memorySize);
memcpy(pMyStructByMalloc, &a, sizeof(int)); // C6378 'pMyStructByMalloc' could be '0'
memcpy((pMyStructByMalloc + sizeof(int)), &s, sizeof(std::string));
memcpy((pMyStructByMalloc + sizeof(int) + +sizeof(std::string)), &b, sizeof(int));
有什么方法可以成功做到这一点吗?
使用 malloc 创建一个等同于 struct 的内存块。
附言。 好的,那么如果结构具有固定的长度并且是
struct MyStruct
{
int a = 1;
float s = 10.0f;
int b = 2;
};
我正在尝试查看是否可以在不使用任何 MyStruct 的情况下“伪造”相同类型的内存并将内存块发送到某个低级函数。(假设我没有引用 MyStruct 代码,但只知道数据结构)
锅标 2
API如下所示
TheAPI(int32 bufferSize, void * data);
我通常这样做,
TheAPI(sizeof(MyStruct), pMyStruct);
但这次我想动态地做到这一点
TheAPI(memorySize , pMyStructByMalloc)
这样,我就可以尝试不同形式的记忆。(不同类型的固定大小结构)
答:
2赞
Pepijn Kramer
11/17/2023
#1
若要复制结构,请提供复制构造函数。 这将确保您的 std::string 也被正确复制,并将启动其生命周期。
#include <cassert>
#include <string>
#include <iostream>
struct MyStruct
{
MyStruct() = default;
~MyStruct() = default;
MyStruct(const MyStruct& rhs) :
a{rhs.a},
s{rhs.s},
b{rhs.b}
{
std::cout << "Copy constructor";
}
// todo copy assignment, move constructor & move assignment
int a = 1;
std::string s = "test";
int b = 2;
};
int main()
{
MyStruct my_struct;
auto copy_of_my_struct{my_struct};
assert(copy_of_my_struct.a == 1);
assert(copy_of_my_struct.s == std::string{"test"});
assert(copy_of_my_struct.b == 2);
}
评论
4赞
NathanOliver
11/17/2023
无需手动提供复制构造函数或任何其他特殊成员函数。默认值将执行正确的操作。
0赞
Pepijn Kramer
11/18/2023
@NathanOliver 你是对的,这是为了明确说明复制可以做什么以及何时被称为;)
0赞
Red.Wave
11/18/2023
至少假装遵循规则 3 并提供 ed 赋值运算符。default
1赞
Ahmed AEK
11/18/2023
#2
如果你有一个缓冲区,并且希望它表示一个对象,你应该使用放置 new 运算符或 C++20 construct_at在特定位置调用构造函数/复制构造函数,这样可以保证对象的生存期被启动(并防止删除未构造的字符串),当你不再使用对象释放任何资源时,你还需要调用析构函数(或 C++20 destroy_at)。
#include <string>
#include <vector>
struct MyStruct
{
int a = 1;
std::string s = "test";
int b = 2;
};
int main()
{
std::vector<char> buffer = std::vector<char>(sizeof(MyStruct));
MyStruct object1 = MyStruct();
MyStruct* object2 = new (&buffer[0]) MyStruct{object1};
object2->~MyStruct(); // destroy object to end its lifetime
return 0;
}
请注意,对齐要求与任何标准类型对齐,因此可用于包含 ,但是如果您从其他地方(如 malloc)获取此内存,则需要确保内存正确对齐,否则操作员将向前推动指针以补偿对齐要求。std::vector
MyStruct
placement new
评论
int memorySize = sizeof(int) + sizeof(std::string) + sizeof(int);
是错误的。最有效的方法是int memorySize = sizeof(MyStruct);
memcpy
std::string
memcpy
std::string
malloc
可以返回 null 指针。警告之所以存在,是因为您没有检查。(但这是你最不关心的问题。