【问题标题】:Scattered 2D array to contiguous 2D array transformation (in C)分散二维数组到连续二维数组的转换(在 C 中)
【发布时间】:2013-11-13 10:22:12
【问题描述】:

我正在尝试在 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 类型而不是 in) ?或者简单地说,“线性化函数会导致内存泄漏吗?”

提前感谢您!

*编辑*

按照 Nicolas Barbey 的建议,我运行 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. 

感谢您的讨论和建议。

【问题讨论】:

  • 不要转换malloc()的返回值。 -- 除此之外:每个malloc() 只调用一次free(),那么就不会泄漏。
  • 那不是二维数组。它是一个指向数组的指针数组。它们相同。如果你完全可以避免它,你也不想成为a three star programmer。 (你可以)。
  • 你的意思是不是 char * temp = (char*)(*array)[i]; char * temp = (*array)[i]; ?
  • @WhozCraig 没必要挑剔我。不,我不能避免成为三星级程序员,因为我必须处理的输入是三星级程序员唯一输入。
  • 有点题外话,但你知道你可以用 valgrind 检查你的程序没有泄漏吗? valgrind.org

标签: c arrays memory-management memory-leaks


【解决方案1】:

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

【讨论】:

    【解决方案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];
    

    【讨论】:

      猜你喜欢
      • 2019-01-23
      • 2012-03-08
      • 2021-11-23
      • 1970-01-01
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      相关资源
      最近更新 更多