2013-11-13 2 views
0

Я пытаюсь создать обобщенную функцию в C, которая принимает 2D-массив ЛЮБОГО типа и копирует его в смежный блок памяти. (Мне нужна эта функция для агрегированных операций с MPI на моих сложных типах данных).Рассеянный 2D-массив для непрерывного преобразования 2D-массива (в C)

Представьте себе У меня есть следующий целочисленный массив

int n = 5; 
int m = 6; 

int** int_array = (int**) malloc(n* sizeof(int*)); 

for (int i = 0; i < n; i++) 
    int_array[i] = (int *) malloc(m * sizeof(int)); 

В этом типе распределения памяти один не может, в принципе, надеюсь, чтобы получить доступ к, скажем, I, J-й ввод int_array с использованием следующих указателей арифметика

int value = (*lcc)[i*m+j]; 

Поэтому я реализовал функцию, которая в основном выделяет новый блок памяти и аккуратно упорядочивает записи int_array, чтобы работа над этим индексом работала.

void linearize(char*** array, int n, int m,unsigned int size_bytes){ 


     char* newarray = (char*)malloc(m*n*size_bytes); 

     //copy array! 
     for (int i = 0;i<n;i++) 
      for(int j = 0;j<m*size_bytes;j++) 
      { 
       newarray[i*m*size_bytes+j] = (*array)[i][j]; 
      } 

     //swap pointers and free old memory!  
     for (int i = 0;i<n;i++) 
     { 
      char * temp = (*array)[i]; 
      (*array)[i] = newarray + i*m*size_bytes ; 
      free(temp); 
     } 

} 

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

Свободно (temp) освобождает всю память, на которую указывает int_array [i], то есть байты m * sizeof (int), доступные из int_array [i] или только первые m байтов (так как он считает, что наш массив имеет тип char, а не in)? Или просто введите: «Ли линеаризованная функция вызывает утечку памяти?»

Спасибо заранее!

* EDIT *

Как предложил Николя Барбе, я побежал VALGRIND проверки на наличие утечек памяти и не нашли.

Так суммировать основные моменты, которые я нашел трудно понять, о поведении программы были:

в функции линеаризации делает следующий код вызвать утечку памяти:

char * temp = (*array)[i]; 
(*array)[i] = newarray + i*m*size_bytes ; 
free(temp); 

НЕТ !! каким-то образом компилятор gnu достаточно умен, чтобы знать, сколько байтов указало на «temp», чтобы освободить. Первоначально я боялся, что если я array [i] является указателем типа int, например, который указывает на ячейку памяти с указанием 5 ints = 5 * 4 байта, free (temp) освободит только первые пять байтов этой памяти.

Еще один момент, чтобы сделать следующее: как освободить уже линеаризованный массив? то есть, если у вас есть:

// first initialize the array. 

int** array = (int**)malloc(5*sizeof(int*); 
for(int i = 0; i< 5;i++) 
    array[i] = (int*) malloc(5*sizeof(int)); 

//now a call to linearize 
linearize(&array,5,5,sizeof(int)); 

... do some work with array .... 

// now time to free array 
free(array[0]); 
free(array); 
//suffices to free all memory pointed to by array[i] and as well as the memory allocated 
// for the pointers. 

Спасибо за обсуждение и предложения.

+0

Не отвергни возвращаемое значение 'таНос()'. - кроме этого: называть 'free()' ровно один раз на 'malloc()', тогда утечек не будет. –

+0

Это не двумерный массив. Это массив указателей на массивы. Они не одинаковы. И вы не хотите быть [трехзвездочным программистом] (http://c2.com/cgi/wiki?ThreeStarProgrammer), если можете вообще этого избежать. (и вы можете). – WhozCraig

+0

Вы имеете в виду вместо char * temp = (char *) (* array) [i]; char * temp = (* array) [i]; ? – kennywise

ответ

0

Вы должны позвонить free() ровно за один звонок за malloc(), чтобы не было утечек памяти. Что означает, что в вашем случае int_array передается функции линеаризации, выделяет блок памяти, отличный от int_array, поэтому вам нужно перебрать int_array[i], освободив каждый int*, чтобы вы проходили мимо, а затем free'ing int_array. Также вам нужно освободить блок, созданный в функции линеаризации.

0

Вот немного стройнее версия с использованием реальных двумерных массивов:

void * linearize(void** array, int n, int m,unsigned int size_bytes){ 

    char (*newarray)[m * size_bytes] = malloc(m*n*size_bytes); 

    //copy array! 
    int i; 
    for (i = 0;i<n;i++) { 
     memcpy(newarray[i], array[i], sizeof(*newarray)); 
     free(array[i]); 
    } 
    free(array); 
    return newarray; 
} 

Использование:

int (*newarray)[m] = linearize(array, n, m, sizeof(**int_array)); 
int value = newarray[i][j]; 
// or 
value = newarray[0][i*m + j]; 
// or 
value = ((int *)newarray)[i*m + j]; 
Смежные вопросы