在C strcut的动态分配方面的最佳策略,并带有许多指针



我想知道什么是在内部带有许多指针的结构的同种内存的最佳策略。

这样:

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 );

相关内容

  • 没有找到相关文章

最新更新