【问题标题】:Contiguous memory allocation for 2D array --- freeing the memory二维数组的连续内存分配---释放内存
【发布时间】:2014-02-19 07:28:21
【问题描述】:

我在运行此程序时在 free() 期间面临堆崩溃,但如果我使用 F10(在 Visual Studio 2010 中)进行调试,我会成功。

我的一段代码:

以下代码用于释放。在这种情况下,有人可以解释二维数组的释放吗?

void Deallocate2D ( SINT32  **pAccess, UINT8 i_ubyNoOfRows )
{
    int i;
    UINT8 *elem;
    if ( NULL == pAccess )
    {
        printf ( "%d>Invalid Params\n", __LINE__ ); 
        return;
    }

    printf ( "\nDeallocate 2D Array..................\n" );

    /* Include the code to deallocate the 2D array */
    {   
            free(pAccess);  

    }
}

以下代码用于内存分配:

SINT32 Allocate2D ( 
                SINT32  ***pAccess, 
                UINT8   i_ubyNoOfRows, 
                UINT8   i_ubyNoOfCols )
{
    SINT32  nResult = -1;
    SINT32  **pAc = NULL;
    UINT8   *pubyPositioner;
    UINT32  unTotalSize;
    int i;

    //unTotalSize = i_ubyNoOfRows * i_ubyNoOfCols;
    printf ( "\nAllocate 2D Array..................\n" );

    /* Include the code to allocate the 2D array */
    {

    /*Contiguous memallocation  pAc*/
    pAc = (SINT32**)malloc(sizeof(SINT32*) * i_ubyNoOfRows);
    if(pAc)
        pubyPositioner = (UINT8*)malloc(sizeof(UINT8) * i_ubyNoOfCols);
    if(pubyPositioner)
        for(i = 0; i < i_ubyNoOfCols; ++i)
            pAc[i] = (SINT32*)pubyPositioner + (i * i_ubyNoOfCols);             

    *pAccess = pAc;

    /*Non contugious allocation*/
    /*  
        pAc = (SINT32**)malloc(sizeof(SINT32*) * i_ubyNoOfRows );
        *pAccess = pAc;
        if(pAc)
         for(i= 0; i < i_ubyNoOfRows; ++i){
            pAc[i] = (SINT32*)malloc(sizeof(SINT32*) + (i * i_ubyNoOfRows) );
            if(pAc[i])
                for(j = 0; j < i_ubyNoOfCols; ++j)
                    pAc[i][j] = (UINT8)malloc(sizeof(UINT8) +   (i_ubyNoOfRows * i_ubyNoOfCols) );

         }

     */
        if(*pAccess != NULL)
            nResult = 0;


    }

    if ( NULL == pAccess )
    {
        printf ( "%d>Invalid Params\n", __LINE__ ); 
        return -1;
    }

    return nResult;
}

填充数组和打印数组的代码:

SINT32 Fill2D ( 
                SINT32  **pnAccess,
                SINT32  *pnData,
                UINT8   i_ubyNoOfRows, 
                UINT8   i_ubyNoOfCols )
{
    SINT16  wRIndex, wCIndex, wDataIndex = 0;   



    printf ( "\nFill 2D Array..................\n" );

    /* Include the code to fill the 2D array with the 1D values */
    {
        for(wRIndex = 0 ; wRIndex < 3; ++wRIndex)
            for(wCIndex = 0; wCIndex < 3; ++wCIndex)
                pnAccess [wRIndex][wCIndex] = pnData[wDataIndex++];

    }

    if ( ( NULL == pnAccess ) \
            || ( NULL == pnData ) )
    {
        printf ( "%d>Invalid Params\n", __LINE__ ); 
        return -1;
    }

    return 0;
}

SINT32 Print2D ( 
                SINT32  **pnAccess,
                UINT8   i_ubyNoOfRows, 
                UINT8   i_ubyNoOfCols )
{
    SINT16  wRIndex, wCIndex;

    if ( NULL == pnAccess )
    {
        printf ( "%d>Invalid Params\n", __LINE__ ); 
        return -1;
    }

    printf ( "\n2D Array..................\n\n" );

    /* Include the code to Print the 2D array in matrix format */
    {
        for(wRIndex = 0 ; wRIndex < i_ubyNoOfRows; ++wRIndex)
        {
            if(wRIndex % 2 == 0)
                printf("\n");
            for(wCIndex = 0; wCIndex < i_ubyNoOfCols; ++wCIndex)
                printf("%d ", pnAccess[wRIndex][wCIndex]); 

        }
    }

    return 0;
}

下面的代码是一种入口点:

void Test2DArray ( void )
{
    SINT32  **pnData = NULL;
    SINT32  nData1[] = { 10, 15, 20, 15, 20, 25, 10, 25, 20 };
    SINT32  nData2[] = { 70, 75, 80, 65, 90, 25, 30, 35, 80 };

    printf ( "\n==================================\n" );
    printf ( "Test 2D Array..................\n" );
    printf ( "==================================\n\n" );

    if ( Allocate2D( &pnData, 3, 3 ) != -1 )
    {
        if ( Fill2D( pnData, nData1, 3, 3 ) != - 1 )
        {
            if ( NULL != pnData )
            {
                Print2D ( pnData, 3, 3 );
                Deallocate2D ( pnData, 3 );
            }
        }
    }

    if ( Allocate2D( &pnData, 3, 3 ) != -1 )
    {
        if ( Fill2D( pnData, nData2, 3, 3 ) != - 1 )
        {
            if ( NULL != pnData )
            {
                Print2D ( pnData, 3, 3 );
                Deallocate2D ( pnData, 3 );
            }
        }
    }
}

【问题讨论】:

  • 请不要投射malloc 返回的指针,经验法则很简单:每个malloc 调用都必须与free 调用配对。无法一次性释放 2D 数组,但您必须分别释放每个指针:char **foo; for (int i=0;i&lt;foo_len;++i) free(foo[i]); free(foo);
  • @EliasVanOotegem 您假设他正在使用兼容的 C 编译器来编译 C 代码。
  • @lundin:没有视觉 C 或 C++ 标签。如果 OP 使用的是 VC++ 编译器,他应该提到
  • 我正在使用 MS Visual Studio,在其中创建 .c 文件来测试代码。感谢您的回复。请看,如果我不使用强制转换,编译器会在编辑器中显示错误消息。 @Lundin 我对连续分配和指针查找表有疑问。我将对此进行更多研究

标签: c multidimensional-array dynamic-memory-allocation


【解决方案1】:
 /*Contiguous memallocation  pAc*/
    pAc = (SINT32**)malloc(sizeof(SINT32*) * i_ubyNoOfRows);
    if(pAc)
        pubyPositioner = (UINT8*)malloc(sizeof(UINT8) * i_ubyNoOfCols);
    if(pubyPositioner)
        for(i = 0; i < i_ubyNoOfCols; ++i)
            pAc[i] = (SINT32*)pubyPositioner + (i * i_ubyNoOfCols);   

这不是连续的内存分配!它是一个基于指针的查找表,分配在一个段中,指向分配在另一个段中的一块内存。

分配一个真正的二维数组的正确代码是:

SINT32 (*pAc)[ubyNoOfCols] = malloc( sizeof(SINT32[i_ubyNoOfCols][i_ubyNoOfRows]) );
...
free(pAc);

请注意,这只会在 C 编译器上编译,因此您不能使用 Visual Studio。


在这种情况下,有人可以解释二维数组的释放吗?

free(pAccess); 

看起来代码只释放指针查找表而不是实际数据。所以我认为这是一个错误:代码包含内存泄漏。

【讨论】:

  • @WhozCraig 哎呀,确实有一些复制/粘贴错误。感谢您指出这一点,已修复。 pAc 在原始代码中被声明为指向指针的指针,这与指向数组的指针不同。是使用 cols 还是 rows 作为第一个维度取决于应用程序的性质,不知道它是基于 "(x, y)" 数学坐标还是其他。
  • 不过,这里的核心问题还是:内存没有相邻分配,deallocation好像有内存泄漏。
【解决方案2】:

让我们看看你的分配代码:

pAc = (SINT32**)malloc(sizeof(SINT32*) * i_ubyNoOfRows);
if(pAc)
    pubyPositioner = (UINT8*)malloc(sizeof(UINT8) * i_ubyNoOfCols);
if(pubyPositioner)
    for(i = 0; i < i_ubyNoOfCols; ++i)
        pAc[i] = (SINT32*)pubyPositioner + (i * i_ubyNoOfCols);             

因此,您首先为i_ubyNoOfRows 指针分配内存。这很好。
然后你继续分配i_ubyNoOfCols bytes,(在你的测试用例中是3个字节),但是你需要i_ubyNoOfCols*i_ubyNoOfRows integers的空间(3*3*4 = 36测试用例中的字节,假设 int 是 32 位类型)。
当你继续初始化你的内存时,你踩到了对malloc()free() 正常运行至关重要的数据。

pAc[i] = (SINT32*)pubyPositioner + (i * i_ubyNoOfCols); 行中的演员表是你一半错误的明显标志。它表明您使用了错误的类型 pubyPostitioner

Ps:你有两个3s 硬编码在Fill2D() 中,即使这个函数得到正确的宽度和高度作为参数传递。

【讨论】:

    【解决方案3】:

    在我的问题中,我想为二维数组分配内存然后释放它。 经过一番研究,我将我的理解解释如下

    1. 使用指针数组分配内存
    double **p;
    int i;
    p= malloc(rows * sizeof(*p));
    for(i= 0; i<rows;++i)
    p[i] = malloc(cols * sizeof(double));
    

    ... ...

    for(i=0;i<rows;i++)
        free(p[i]);
     free(p);
    
    1. 使用指针查找表分配
    double **p;
    double *elem;
    
    elem = malloc(rows * cols * sizeof(double));
    p = malloc(cols * sizeof(double*));
    for (i = 0; i<rows;++i)
    p[i] =  elem + ( i*cols);
    
    free(p);
    
    1. 连续分配
    double **p;
    p = malloc( rows * cols * sizeof(double*));
    /*Accessing / printing values ... assume values are assinged to this array*/
    for(i=0; i <rows; ++i)
     for(j = 0; j< cols; ++j)
      printf("%d",p[j + (i * cols)]);
    
    free(p)
    

    【讨论】:

      猜你喜欢
      • 2022-01-06
      • 2016-03-15
      • 2016-01-08
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      • 2020-01-18
      • 2015-07-09
      • 2012-11-12
      相关资源
      最近更新 更多