【发布时间】:2021-05-11 12:57:56
【问题描述】:
假设,我想分配一块内存并在该块前面存储一些元数据。 为此,我想出了这个:
#include <stdlib.h>
#include <stddef.h>
typedef struct metadata_s{
char someMetaData[3];
}metadata_t;
typedef struct mem_block_s{
metadata_t metadata;
//Insert padding so 'data' has fundamental alignment
char padding[sizeof(max_align_t) == sizeof(metadata_t) ? 0 : sizeof(max_align_t) - (sizeof(metadata_t)) % sizeof(max_align_t)];
char data[];
}mem_block_t;
void* allocateMemory(size_t size){
mem_block_t* newMemBlock = malloc(sizeof(mem_block_t) + size);
if(newMemBlock != NULL){
return(newMemBlock->data);
}
return(NULL);
}
int main(void){
double* doubleArray = allocateMemory(100 * sizeof(double));
if(doubleArray != NULL){
doubleArray[0] = 1.0f;
}
}
这有多个问题:
- C 只保证在结构的开头没有填充,
mem_block_s结构内可能有额外的填充 - 最终,我返回并将指向
char数组的指针分配给(在这种情况下)double指针(我可以这样做吗?)
相反,我可以做类似的事情
typedef struct mem_block_s{
metadata_t metadata;
void* data;
}mem_block_t;
并分别为data 分配内存,但是只要给定data 指针,我将很难访问元数据。
什么是正确的 C 方法来做这样的事情?
【问题讨论】:
-
去掉padding成员,将
data成员改为char _Alignas(max_align_t) data[];。这既简化了代码,又解决了编译器假设插入不必要的填充的问题。 -
Re“(我可以这样做吗?)”:是的,也不是。可以说,您可以通过将其写入为
double来为内存创建一个有效的类型,但该标准并没有以一种正式的方式来说明这一点。我希望它不会成为当前编译器的问题。 (也可以,因为 C 标准几乎没有禁止;您允许这样做。您的问题实际上应该是行为是否已定义。) -
谢谢,我忘了 _Alignas。这简化了事情。
标签: c dynamic-memory-allocation