我想知道什么是在内部带有许多指针的结构的同种内存的最佳策略。
这样:
struct Test{
long unsigned int size;
double *A;
int *B;
double *C;
};
然后我可以使用许多分配,例如:
struct Test *alloc_test(long unsigned int size){
struct Test *ans = (struct Test*)malloc(sizeof(struct Test));
if(ans == NULL){
return NULL;
}
ans->size = size;
ans->A = (double *)malloc(sizeof(double)*size);
if(ans->A == NULL){
free(ans);
return NULL;
}
ans->B = (int *)malloc(sizeof(int)*size);
if(ans->B == NULL){
free(ans->A);
free(ans);
return NULL;
}
ans->C = (double *)malloc(sizeof(double)*size);
if(ans->C == NULL){
free(ans->A);
free(ans->B);
free(ans);
return NULL;
}
return ans;
}
,或者我可以使用单个分配,例如:
struct Test *alloc_test(long unsigned int size){
long unsigned int mem_size = sizeof(struct Test) + sizeof(double)*2*size + sizeof(int)*size;
struct Test *ans = (struct Test*)malloc(mem_size);
if(ans == NULL){
return NULL;
}
ans->size = size;
ans->A = ans + sizeof(struct Test);
ans->B = ans->A + sizeof(double)*size;
ans->C = ans->B + sizeof(int)*size;
return ans;
}
这是可能的,因为不应重新介绍此对象。在这种情况下,有人知道每个人的优势吗?
两者都是可能的,而您选择的是自由。但是,您应该遵守对齐约束(也许使用alignas
和<stdalign.h>
的CC_3进行单个分配变体)
还阅读有关灵活数组成员的阅读,该成员允许在特定情况下单个malloc
,您只有一个一个阵列成员。
请注意,malloc
的每个调用都有其开销(在内存中,也许要额外消耗一个或两个单词来进行内部管理,并且及时;典型的malloc
在我的桌面上的微秒少于微秒)。
用于长期计划,例如服务器您可能还会关心分裂(对于大多数短期寿命应用程序而言不是问题)
第二种方法(单个malloc
)可能更友好地缓存。大多数情况下,您不在乎。
btw(如Chux所说)
ans->A = ans + sizeof(struct Test);
是错误的,因为指针算术发生在尖头类型的单位中。您可能想要
ans->A = ((char*)ans)+sizeof(struct Test);
实际上,您应该更仔细地计算mem_size
(在其中也使用alignof
,或假设alignof(long unsigned int) >= alignof(double)
等)然后更喜欢
char* ad = malloc(mem_size);
if (!ad) return NULL;
ans = ad;
ans->A = ad + sizeof(struct Test);
mem_size
的确切计算(需要有条件的和使用alignof
),而真实的代码则作为练习(我太la脚了,无法在此处解释)。
在计划A中,您可以获得内存围栏,特定于体系结构的内存对准,实现核心的能力。当然,人们可以对此进行一些重新处理,以便处理错误并没有散布在各个方面 - 但这是个人风格的问题。
在计划B中,您将失去所有自动的东西 - 您将不得不照顾好它。然后可能很难阅读。
根据分配器的不同,您可能会比一个巨型块更容易找到多个较小的内存。因此,在策略方面,您必须做出自己的决定 - 如果您有自己的分配者。
让我向您展示如何以更清洁的方式处理错误:
struct Test *alloc_test(long unsigned int size)
{
struct Test *ans = malloc(sizeof(struct Test));
if(ans == NULL)
{
return NULL;
}
ans->size = size;
ans->A = malloc(sizeof(ans->A) * size);
ans->B = malloc(sizeof(ans->B) * size);
ans->C = malloc(sizeof(ans->C) * size);
if(ans->A == NULL || ans->B == NULL || ans->C == NULL)
{
free(ans->A);
free(ans->B);
free(ans->C);
free(ans);
return NULL;
}
return ans;
}
您可能不需要使用多个调用malloc()
或完全处理对齐。
如果所有动态分配的数组始终具有相同数量的元素,请使用包含实际 values 的struct
,并创建struct
的数组:
typedef struct data
{
double A;
double B;
int C;
};
分配:
struct data *dataPtr = malloc( size * sizeof( *dataPtr ) );
DealLocation:
free( dataPtr );
简单而易于理解。
如果您需要随身携带数据,请使用具有struct data
的灵活数组的struct
:
typedef struct test
{
unsigned long size;
struct data[];
}
分配:
struct test *testPtr = malloc( sizeof( *testPtr ) + size * sizeof( testPtr->data ) );
testPtr ->size = size;
DealLocation:
free( testPtr );