有一个技巧允许单个malloc,但也必须权衡使用更标准的多个malloc 方法。
如果 [and only if],一旦分配了SOME_STRUCT 的DatatypeN 元素,它们确实不需要以任何方式重新分配,任何其他代码也不会在其中任何一个上执行free,您可以执行以下操作[假设PDATATYPEn指向DATATYPEn]:
PSOME_STRUCT
alloc_some_struct(void)
{
size_t siz;
void *vptr;
PSOME_STRUCT sptr;
// NOTE: this optimizes down to a single assignment
siz = 0;
siz += sizeof(DATATYPE1);
siz += sizeof(DATATYPE2);
siz += sizeof(DATATYPE3);
...
siz += sizeof(DATATYPE12);
sptr = malloc(sizeof(SOME_STRUCT) + siz);
vptr = sptr;
vptr += sizeof(SOME_STRUCT);
sptr->Pdatatype1 = vptr;
// either initialize the struct pointed to by sptr->Pdatatype1 here or
// caller should do it -- likewise for the others ...
vptr += sizeof(DATATYPE1);
sptr->Pdatatype2 = vptr;
vptr += sizeof(DATATYPE2);
sptr->Pdatatype3 = vptr;
vptr += sizeof(DATATYPE3);
...
sptr->Pdatatype12 = vptr;
vptr += sizeof(DATATYPE12);
return sptr;
}
然后,当你完成后,只需执行free(sptr)。
上面的sizeof应该足以为子结构提供正确的对齐方式。如果没有,您必须用提供必要对齐的宏(例如SIZEOF)替换它们。 (例如)对于 8 字节对齐,类似于:
#define SIZEOF(_siz) (((_siz) + 7) & ~0x07)
注意:虽然这一切都可以做到,但对于像可变长度字符串结构这样的事情来说更常见:
struct mystring {
int my_strlen;
char my_strbuf[0];
};
struct mystring {
int my_strlen;
char *my_strbuf;
};
是否值得 [潜在的] 脆弱性值得商榷(即有人忘记并在单个元素上执行 realloc/free)。如果单个 malloc 对您来说是一个高优先级,那么更简洁的方法是嵌入实际结构而不是指向它们的指针。
否则,只需按照 [更多] 标准方式进行 12 次单独的 malloc 调用,然后再进行 12 次 free 调用。
不过,它是一种可行的技术,尤其是在内存受限的小系统上。
这是涉及每个元素分配的 [更多] 常用方法:
PSOME_STRUCT
alloc_some_struct(void)
{
void *vptr;
PSOME_STRUCT sptr;
sptr = malloc(sizeof(SOME_STRUCT));
// either initialize the struct pointed to by sptr->Pdatatype1 here or
// caller should do it -- likewise for the others ...
sptr->Pdatatype1 = malloc(sizeof(DATATYPE1));
sptr->Pdatatype2 = malloc(sizeof(DATATYPE2));
sptr->Pdatatype3 = malloc(sizeof(DATATYPE3));
...
sptr->Pdatatype12 = malloc(sizeof(DATATYPE12));
return sptr;
}
void
free_some_struct(PSOME_STRUCT sptr)
{
free(sptr->Pdatatype1);
free(sptr->Pdatatype2);
free(sptr->Pdatatype3);
...
free(sptr->Pdatatype12);
free(sptr);
}