2011-12-23 2 views
0

У меня есть структура, которая представить свой элемент данныхвыделения памяти на структуру в чистом C

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

другой структуры, которые содержат множество этих элементов и некоторые другие данные

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

и я должен быть массив таких массивов

struct myArray *myMatrix; 

Но у меня проблема с распределением памяти. Количество элементов в myArray может быть другим, в myMatrix тоже, поэтому мне нужно распределить память динамически. Каков корректный способ выделения и освобождения памяти в этой ситуации?

+6

С [ '' malloc' и free'] (http://linux.die.net/man/3/malloc) –

ответ

5

Вот небольшой пример того, как вы могли бы выделить (malloc) и DEALLOCATE (free) динамический массив struct myElement в struct myArray. Обратите внимание, что вам нужно будет отслеживать размер массива, поэтому я добавил 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 достаточно памяти для Х сумма struct myArray s, затем for каждый struct myArray элемент в этом массиве, вы бы назвали allocate_elements. Затем перебирайте каждый элемент массива, как только вы закончите с ним, и вызовите free_elements.

+0

+1 для изменения структуры для отслеживания длин. Я постулировал отдельный массив, чтобы сохранить/указать эту информацию. –

+0

Благодарим вас за полный и информативный ответ. – Padavan

+0

У вас есть возможность вызывать malloc безумное количество раз в зависимости от количества элементов в переменной myMatrix. Как вы обрабатываете фрагментацию памяти и накладные расходы на распределение? –

0
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; 
+0

myMatrix не имеет элементов называется 'field1' т.д. –

+0

@JonathanLeffler: благодаря! исправлено. – wallyk

0

Использование malloc выделить память:

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

Использование free аналогичным образом, чтобы освободить память, как только вы сделали с ним.

+0

спасибо, этот workd. И разве это так? для (int i = 0; i Padavan

+0

@Padavan: Да, это место на. –

0
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 указывает, сколько элементов в соответствующем элементе матрицы. Код проверяет успешное выделение памяти, но не реагирует на отказ распределения.

0

Что-то вроде этого должно работать, хотя оно не является отличным решением с большим количеством отдельных распределений, а дальше - лучшее решение. Я попытался сделать имена переменных, описывающие, что они держат.

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

В моде не только два обращения к распределителю независимо от того, различные длины. Таким образом, существует гораздо больше фрагментации памяти и меньше затрат времени на распределение. Единственный недостаток второго метода заключается в том, что если вы не будете осторожны с проверкой границ, очень легко испортить данные в массиве, не зная, так как память «принадлежит» вам, и, следовательно, ОС не будет бить вас за нарушение доступа ,

+0

'new' и' delete' являются C++, 'malloc 'и' free' - это путь в C.;) – AusCBloke

+0

Извините, я подумал, что он сказал c и C++ fixing now. –

0

Для динамического выделения и освобождения памяти вам необходимо использовать функции malloc и free. Пожалуйста, используйте следующую ссылку.

#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 вы» попросил.