计算标记联合的malloc大小(不过度分配)

jq6vz3qz  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(80)

假设我有以下结构:

typedef struct MyObject {
    char* tag;
    union {
        BigObject b;     // imagine this is 5MB
        SmallObject s;   // imagine this is 8 bytes
    } u;
}

从标准(从this answer复制):
一个联合体的大小足以包含其最大的数据成员。每个数据成员都像结构的唯一成员一样分配。
有没有一种方法可以让一个特定的结构体的大小精确到malloc?这将是类似于tag*(8)+ padding(?)+ [小或大对象大小](?)。换句话说,我怎样才能得到MyObject o; sizeof(o)的值,同时考虑到正确的union-艾德对象大小?

xjreopfe

xjreopfe1#

当为一个结构分配内存时,你必须为整个结构给予足够的空间,即使你只使用包含联合的较小成员。
如果您没有分配足够的内存,并且要写入较大的成员,则需要调用undefined behavior来写入已分配的内存。即使你只写信给较小的成员,也不能保证你不会有问题。
例如,如果你这样做:

MyObject *o1, *o2;
o1 = malloc(sizeof(char *) + sizeof(SmallObject)); 
o2 = malloc(sizeof(char *) + sizeof(SmallObject)); 
o1->tag = "small";
// assign values in o1.u.s
*o2 = *o1;

最后一行的赋值会触发undefined行为,因为整个结构体都会被复制。
你的结构体目前定义的方式,最好只分配sizeof(struct MyObject)字节,然后完成它。
作为替代方案,您可以使用指向包含结构的指针,并分别为它们分配空间。

typedef struct MyObject {
    char* tag;
    union {
        BigObject *b;
        SmallObject* s;
    } u;
} MyObject;

...
MyObject *o = malloc(sizeof(MyObject));
o->tag = "big";
o->u.b = malloc(sizeof(BigObject));

相关问题