0

ANY 型の 2D 配列を取り、それを連続したメモリ ブロックにコピーするジェネリック関数を C で作成しようとしています。(複雑なデータ型の MPI で集計操作を行うには、この関数が必要です)。

次の整数配列があると想像してください

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

このタイプのメモリ割り当てでは、原則として、次のポインタ演算を使用して int_array の i,j 番目のエントリにアクセスすることは期待できません。

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

}

上記の関数をあらゆる種類の配列型で動作させたかったので、char ポインターを使用してバイト単位で操作を行いました。関数をテストしたところ、これまでのところ機能していますが、メモリの割り当て解除についてはわかりません。

free(temp) は int_array[i] が指すメモリ全体、つまり int_array[i] からアクセス可能な m*sizeof(int) バイト、または最初の m バイトのみを解放しますか (配列が char 型であると見なされるため)ではなく)?または簡単に言えば、「線形化機能はメモリ リークを引き起こしますか?」

前もって感謝します!

*編集*

Nicolas Barbey が提案したように、メモリ リークがないかどうか valgrind チェックを実行しましたが、何も見つかりませんでした。

したがって、プログラムの動作について理解するのが難しいと感じた主なポイントを要約すると、次のとおりです。

関数 linearize では、次のコードがメモリ リークを引き起こします。

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

いいえ!!どういうわけか、gnuコンパイラは、「temp」が指すバイト数を解放するのに十分なほどスマートです。当初、もしarray[i] が int 型のポインタである場合、たとえば 5 ints = 5*4 バイトのメモリ位置を指している場合、free(temp) は最初の 5 つだけを解放するのではないかと心配していました。そのメモリのバイト。

もう 1 つのポイントは、既に線形化された配列を解放する方法です。それはあなたが持っている場合です:

// 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. 

議論と提案をありがとう。

4

2 に答える 2

0

これは、実際の 2 次元配列を使用した、わ​​ずかにスリムなバージョンです。

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];
于 2013-11-13T10:58:38.993 に答える
0

メモリ リークが発生しないようにするには、 1 回の呼び出しfree()で正確に 1 回呼び出す必要があります。malloc()つまり、あなたの場合int_array、線形化関数に渡されて、割り当て以外のメモリブロックが割り当てられるため、トラバースするそれぞれを解放してint_arrayから、それ自体を解放することをループする必要があります。また、線形化関数で作成されたブロックも解放する必要があります。int_array[i]int*int_array

于 2013-11-13T10:38:29.833 に答える