我正在尝试在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_array的第i个第i个条目
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类型而不是in)?或者简单地说,“线性化函数会导致任何内存泄漏吗?”
提前谢谢!
* 编辑 *
根据Nicolas Barbey的建议,我对内存泄漏进行了valgrind检查,但没有找到。
总结一下我发现难以理解的关于该计划行为的要点是:
函数线性化中的以下代码会导致内存泄漏:
char * temp = (*array)[i];
(*array)[i] = newarray + i*m*size_bytes ;
free(temp);
NO !!不知何故,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 :(得分:0)
您需要为每个free()
调用malloc()
一个调用,以便不会出现内存泄漏。在您的情况下,int_array
传递给线性化函数意味着分配除int_array
分配之外的内存块,因此您需要循环int_array[i]
释放您遍历的每个int*
其次是自由int_array
。此外,您还需要释放在线性化功能中创建的块。
答案 1 :(得分: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];