C中动态分配的最佳策略,用于具有许多指针的strcut

时间:2017-09-19 17:30:34

标签: c malloc

我想知道为具有多个指针的结构分配内存的最佳策略是什么。

像这样:

&&

然后我可以使用很多分配,如下所示:

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

这可能是因为这个对象不应该被重新分配。在这种情况下,有谁知道每个人的优势?

4 个答案:

答案 0 :(得分:3)

两者都是可能的,你选择哪一个是你的自由。但是,您应该遵守alignment限制(可能使用alignas alignof<stdalign.h>作为单一分配变体

另请阅读flexible array members,在特定情况下,只允许一个malloc 一个数组成员。

请注意,对malloc的每次调用都有其开销(在内存中,可能会为内部管理消耗额外的一两个字,并且及时;一个典型的malloc在我的内存上花费不到一微秒桌面)。

对于长效计划,例如您可能也关心fragmentation的服务器(对于大多数短期应用程序而言不是问题)

第二种方法(单malloc)可能稍微更友好cache。大多数情况下,你不会在意。

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)和真实代码留作练习(我在这里解释它太蹩脚了)。

答案 1 :(得分:3)

在Plan A中,您可以获得内存防护,特定于体系结构的内存对齐,以及重新分配的能力。当然,人们可以稍微重构一下,以便错误处理不会分散 - 但这是个人风格的问题。

在B计划中,你失去了所有自动化的东西 - 你必须要照顾它。然后可能会很难阅读。

根据您的分配器,您可能更容易找到多个较小的内存块而不是一个兆块。所以,从战略角度来说,你必须做出自己的决定 - 如果你有自己的分配器。

答案 2 :(得分:1)

让我告诉你如何以更清洁的方式处理第一种情况的错误:

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

答案 3 :(得分:0)

您可能不需要使用多次调用malloc()或完全处理对齐。

如果所有动态分配的数组总是具有相同数量的元素,请使用包含实际struct,并创建struct的数组:

typedef struct data
{
    double A;
    double B;
    int C;
};

分配:

struct data *dataPtr = malloc( size * sizeof( *dataPtr ) );

取消分配:

free( dataPtr );

简单易懂。

如果您需要随身携带数据,请使用struct灵活数组struct data

typedef struct test
{
    unsigned long size;
    struct data[];
}

分配:

struct test *testPtr = malloc( sizeof( *testPtr ) + size * sizeof( testPtr->data ) );
testPtr ->size = size;

取消分配:

free( testPtr );