【问题标题】:how do I allocate memory for some of the structure elements如何为某些结构元素分配内存
【发布时间】:2016-09-22 10:10:43
【问题描述】:

我想为结构的某些元素分配内存,这些元素是指向其他小型结构的指针。如何以最佳方式分配和取消分配内存?

例如:

 typedef struct _SOME_STRUCT {
    PDATATYPE1   PDatatype1;
    PDATATYPE2   PDatatype2;
    PDATATYPE3   PDatatype3;

    .......

    PDATATYPE12   PDatatype12;
} SOME_STRUCT, *PSOME_STRUCT;

我想为 PDatatype1,3,4,6,7,9,11 分配内存。我可以使用单个 malloc 分配内存吗?或者只为这些元素分配内存的最佳方法是什么以及如何释放分配的整个内存?

【问题讨论】:

    标签: memory-management malloc structure dynamic-memory-allocation calloc


    【解决方案1】:

    有一个技巧允许单个malloc,但也必须权衡使用更标准的多个malloc 方法。

    如果 [and only if],一旦分配了SOME_STRUCTDatatypeN 元素,它们确实不需要以任何方式重新分配,任何其他代码也不会在其中任何一个上执行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);
    }
    

    【讨论】:

    • 我可以这样做,但 Klocwork 的问题是它会坚持检查每个 malloc 调用的返回值! (我说的是你提到的标准方式)
    • 我会重新询问 Ates 关于为什么必须使用指针 的问题。 IMO,除非您需要使用 DATATYPEn 而不是 PDATATYPEn 重新分配单个元素似乎更好。我发布的任何一种方法都应该通过验证,因为它们都是合法的。但是,我敢打赌 klocwork 会抱怨这个把戏。但是,有一种“子池”分配方法[我没有发布]可以减少 malloc 的数量。如果您能多解释一下您的要求/限制,我也许可以相应地调整我的答案。
    • 只是我必须使用之前在我的项目中定义的预定义结构,并且它已在其他各个地方使用,因此我无法更改结构本身。
    • 如果结构已经定义,我认为已经有 alloc/free 函数[比如我的“std”版本]——最好使用这些函数。在我提到的大 if 上,是否有人对单个元素执行“带外”realloc/free?也就是说,一旦您创建了外部“SOME”结构,它们是否会保持数据 ptr 值不变?没有人做 sptr->pdata1 = realloc(...),但他们被允许做 sptr->pdata1->xxx = 32]?如果yes,子池方法可以工作。否则,回退到 std [如果可能,使用预先存在的 fncs]。听起来你一定会这样做,所以无论哪种方式都不要担心。
    【解决方案2】:

    如果您的结构包含其他结构作为元素而不是指针,您可以一次性为组合结构分配内存:

    typedef struct _SOME_STRUCT {
        DATATYPE1   Datatype1;
        DATATYPE2   Datatype2;
        DATATYPE3   Datatype3;
    
        .......
    
        DATATYPE12   Datatype12;
    } SOME_STRUCT, *PSOME_STRUCT;
    
    PSOME_STRUCT p = (PSOME_STRUCT)malloc(sizeof(SOME_STRUCT));
    
    // Or without malloc:
    PSOME_STRUCT p = new SOME_STRUCT();
    

    【讨论】:

    • 如果它有其他结构而不是它们的指针,我可以通过SOME_STRUCT 直接使用它们而不分配内存,不是吗?
    • 是的,如果你定义一个变量为:SOME_STRUCT s;
    • 能否在原题中加入需要使用指针的条件?在这种情况下,最直接的方法是对子结构单独进行 malloc。
    猜你喜欢
    • 1970-01-01
    • 2020-10-07
    • 2018-11-19
    • 1970-01-01
    • 2013-08-30
    • 2023-01-12
    • 2016-01-27
    • 2020-02-03
    相关资源
    最近更新 更多