簡體   English   中英

內存分配以純C結構

[英]Memory allocation to struct in pure C

我有一個結構,它表示我的數據元素

struct myElement
{
    int field1;
    int field2;
    int field3;    
};

另一個結構,包含此元素的數組和一些其他數據

struct myArray 
{
    struct myElement *elements;
    int someData;
};

我需要像這樣的數組的數組

struct myArray *myMatrix;

但是我在內存分配上有問題。 myArray中的元素數量可以不同,myMatrix中的元素數量也可以不同,因此我需要動態分配內存。 在這種情況下,分配和釋放內存的正確方法是什么?

這是一個小示例,說明如何在struct myArray分配( malloc )和釋放( free )動態struct myElement數組。 還要注意,您將需要跟蹤數組的大小,因此我添加了size_t elements_len; struct myArray (請使用camelCase和下划線的組合-我在C語言中使用下划線,但不想修改您的標識符):

#include <stdlib.h>

struct myElement
{
    int field1;
    int field2;
    int field3;    
};

struct myArray 
{
    struct myElement *elements;
    size_t elements_len;
    int someData;
};

void allocate_elements(struct myArray *m, size_t length)
{
   m->elements = malloc(length * sizeof( *m->elements) );
   m->elements_len = length;
}

void free_elements(struct myArray *m)
{
   free(m->elements);
   m->elements = NULL;  /* point to NULL to signify no array allocated */
   m->elements_len = 0; /* length of 0 also signifies no elements/no array */
}

int main(void)
{
   struct myArray ma;

   allocate_elements(&ma, 5);
   free_elements(&ma);

   return 0;
}

應用類似的邏輯以獲取struct myArray的動態數組。 你會malloc足夠的內存為X量struct myArray S,則for每個struct myArray數組中元素,你會打電話allocate_elements 完成后,遍歷數組中的每個元素,並調用free_elements

int  num_elements = 1234;  // whatever

struct myArray *myMatrix;

myMatrix = malloc (num_elements * sizeof (*myMatrix));
if (!myMatrix)
     // error

// subsequent use of myMatrix is just like it had been statically dimensioned:
myMatrix [0].someData =  343;

myMatrix [1].someData =  323;

使用malloc分配內存:

myMatrix = malloc(sizeof(myArray)*dim1);
for (int i = 0; i < dim1; i++)
    myMatrix[i].elements = malloc(sizeof(myElement)*dim2);

完成使用后,以類似方式使用free釋放內存。

struct myArray *myMatrix = malloc(Nentries * sizeof(*myMatrix));
if (myMatrix != 0)
{
    for (int i = 0; i < Nentries; i++)
    {
        myMatrix[i].elements = malloc(Nelements[i] * sizeof(myElement));
        if (myMatrix[i].elements != 0)
        {
            for (int j = 0; j < Nelements[i]; j++)
            {
                myElement *e = &myMatrix[i].elements[j];
                e->field1 = 0;
                e->field2 = 1;
                e->field3 = 2;
            }
            myMatrix[i].someData = 37;
        }
    }
}

我假設Nentries表示矩陣中有多少個元素,而數組Nelements每個元素Nelements表示矩陣的相應元素中有多少個元素。 該代碼測試內存分配是否成功,但不會對分配失敗做出反應。

像這樣的事情應該可以工作,盡管對於這么多單獨的分配來說,這不是一個很好的解決方案,而進一步下去則是一個更好的解決方案。 我試圖使變量名描述它們的含義。

int arrayOfSubArrayLengths={9,5,10,50,...};
int lengthOfMyMatrix=something;

myMatrix= (myArray*) malloc( sizeof(myArray) * lengthOfMyMatrix);

for(int i=0; i<lengthOfMyMatrix; ++i)
{
    myMatrix[i].elements=new myElement[arrayOfSubArrayLengths];
    myMatrix[i].someData=whatever;
}

刪除:

for(int i=0; i<lengthOfMyMatrix; ++i)
{
    free( myMatrix[i].elements );
}
free( myMatrix );

但是,正如我所說的,分配這么多不是一個好的解決方案。 這可能會導致一些嚴重的內存碎片,具體取決於lengthOfMyMatrix的大小。 同樣,對分配器的如此多次調用可能會使速度變慢,這再次取決於lengthOfMyMatrix的大小。 這是一個更好的解決方案:

int arrayOfSubArrayLengths={9,5,10,50,...};
int lengthOfMyMatrix=something;
int sumOfSubArrayLengths=someNumber;

myArray* fullArray=(myElement*) malloc( sizeof(myElement) * sumOfSubArrayLengths);

myMatrix= (myArray*) malloc( sizeof(myArray) * lengthOfMyMatrix);

int runningSum=0;

for(int i=0; i<lengthOfMyMatrix; ++i)
{
    myMatrix[i].elements = &fullArray[runningSum];
    runningSum += arrayOfSubArrayLengths[i];
    myMatrix[i].someData = whatever;
}

刪除:

free( fullArray );
free( myMatrix );

以這種方式,無論長度如何,都只有兩次調用分配器。 因此,存在更多的內存碎片和更少的分配開銷時間。 第二種方法的缺點是,如果您不小心進行邊界檢查,那么很容易在不知道的情況下破壞數組中的數據,因為內存“屬於”您,因此操作系統不會因訪問沖突而踢您。

您需要使用mallocfree函數來動態分配和釋放內存。 請參考以下內容。

#include <stdio.h>
#include <stdlib.h>

int main()
{

    struct myElement {
        int field1;
        int field2;
        int field3;
    };

    struct myArray {
        struct myElement *elements;
        int someData;
    };

    struct myArray *myMatrix = NULL;

    int n_myarray = 0;
    int n_elements = 0;
    int i, j;

    printf("How many myArray's do you want? ");
    scanf("%d", &n_myarray);

    printf("How many elements do you want in each array? ");
    scanf("%d", &n_elements);

    /* memory allocation starts here */
    if ((myMatrix = (struct myArray *) malloc((int)sizeof(struct myArray) * n_myarray)) == NULL) {
        printf("ERROR: unable to allocate array\n");
        return 1;
    }

    for (i=0 ; i<n_myarray ; i++) {
        if ((myMatrix[i].elements = (struct myElement *) malloc((int)sizeof(struct myElement) * n_elements)) == NULL) {
            printf("ERROR: unable to allocate array elements\n");
            free(myMatrix);
            return 1;
        }

        /* initialization of other members of struct myArray goes here */
        myMatrix[i].someData = 123;

        /* initialization of members of struct myElement goes here */
        for (j=0 ; j<n_elements ; j++) {
            myMatrix[i].elements[j].field1 = 123;
            myMatrix[i].elements[j].field2 = 123;
            myMatrix[i].elements[j].field3 = 123;
        }
    }

    /* do your calculations here */
    /* I'm printing the values */

    for (i=0 ; i<n_myarray ; i++) {
        printf("myMatrix[%d].someData : %d \n", i, myMatrix[i].someData);
        for (j=0 ; j<n_elements ; j++) {
            printf("myMatrix[%d].elements[%d].field1 : %d \n", i, j, myMatrix[i].elements[j].field1);
            printf("myMatrix[%d].elements[%d].field2 : %d \n", i, j, myMatrix[i].elements[j].field2);
            printf("myMatrix[%d].elements[%d].field3 : %d \n", i, j, myMatrix[i].elements[j].field3);
        }
    }

    /* memory deallocation (free) starts here */

    for (i=0 ; i<n_myarray ; i++) {
        free(myMatrix[i].elements);
    }
    free(myMatrix);

    return 0;
}

> ./a.out
How many myArray's do you want? 2
How many elements do you want in each array? 5
myMatrix[0].someData : 123
myMatrix[0].elements[0].field1 : 123
myMatrix[0].elements[0].field2 : 123
myMatrix[0].elements[0].field3 : 123
myMatrix[0].elements[1].field1 : 123
myMatrix[0].elements[1].field2 : 123
myMatrix[0].elements[1].field3 : 123
myMatrix[0].elements[2].field1 : 123
myMatrix[0].elements[2].field2 : 123
myMatrix[0].elements[2].field3 : 123
myMatrix[0].elements[3].field1 : 123
myMatrix[0].elements[3].field2 : 123
myMatrix[0].elements[3].field3 : 123
myMatrix[0].elements[4].field1 : 123
myMatrix[0].elements[4].field2 : 123
myMatrix[0].elements[4].field3 : 123
myMatrix[1].someData : 123
myMatrix[1].elements[0].field1 : 123
myMatrix[1].elements[0].field2 : 123
myMatrix[1].elements[0].field3 : 123
myMatrix[1].elements[1].field1 : 123
myMatrix[1].elements[1].field2 : 123
myMatrix[1].elements[1].field3 : 123
myMatrix[1].elements[2].field1 : 123
myMatrix[1].elements[2].field2 : 123
myMatrix[1].elements[2].field3 : 123
myMatrix[1].elements[3].field1 : 123
myMatrix[1].elements[3].field2 : 123
myMatrix[1].elements[3].field3 : 123
myMatrix[1].elements[4].field1 : 123
myMatrix[1].elements[4].field2 : 123
myMatrix[1].elements[4].field3 : 123
>

請確保以下內容:

  • 對於每個malloc應該有一個free
  • 在使用通過malloc分配的內存之前,必須檢查malloc是否成功分配了您請求的內存塊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM