分散二维数组到连续二维数组的转换(C)

分散二维数组到连续二维数组的转换(C),c,arrays,memory-management,memory-leaks,C,Arrays,Memory Management,Memory Leaks,我试图在C中创建一个通用函数,它接受任何类型的2D数组并将其复制到一个连续的内存块中。(我需要这个函数来对复杂数据类型的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) ); 因此,我实现

我试图在C中创建一个通用函数,它接受任何类型的2D数组并将其复制到一个连续的内存块中。(我需要这个函数来对复杂数据类型的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_数组的条目进行了整齐的排序,这样上面的索引就可以工作了

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

}
不!!不知何故,gnu编译器足够聪明,可以知道“temp”指向的空闲字节数。最初我担心如果I array[I]是int类型的指针,例如,它指向一个内存位置,比如说5 int=5*4字节,那么空闲(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. 
//首先初始化数组。
int**数组=(int**)malloc(5*sizeof(int*);
对于(int i=0;i<5;i++)
数组[i]=(int*)malloc(5*sizeof(int));
//现在需要线性化
线性化(&数组,5,5,sizeof(int));
…对数组执行一些操作。。。。
//现在是释放阵列的时候了
自由(数组[0]);
自由(数组);
//足以释放数组[i]指向的所有内存以及分配的内存
//为了指针。

感谢您的讨论和建议。

您需要调用
free()
每个
malloc()只调用一次
为了避免内存泄漏。这意味着在您的情况下,
int\u数组
被传递到线性化函数,该函数分配除
int\u数组
分配之外的内存块,因此您需要循环
int\u数组[i]
释放您遍历的每个
int*
,然后释放
int\u数组
本身。您还需要释放在线性化函数中创建的块。

这里有一个使用实际二维数组的稍微精简的版本:

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

不要强制转换
malloc()
的返回值——除此之外:每个
malloc()
只调用
free()
一次,那么就不会有泄漏。这不是二维数组。它是指向数组的指针数组。它们不一样。如果可以避免,你也不想这样做。(你可以)。你的意思是说不用char*temp=(char*)(*array)[i];char*temp=(*array)[i];?@WhozCraig不需要挑剔我。不,我不能避免成为一名三星级程序员,因为我必须处理的输入是三星级程序员唯一的输入。有点离题,但你知道你可以用valgrind检查你的程序没有漏洞吗?
// 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. 
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];