繁体   English   中英

如何释放结构中的动态二维数组?

[英]How to free dynamic 2d array that's in a struct?

我在这个结构中有一个动态的2d数组:

struct mystruct{
    int mySize;
    int **networkRep;
};

在我的代码块中,我使用它如下:

struct myStruct astruct[100];
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
// do stuff...
int i;
for(i=0; i<100; i++)
    freeMatrix(astruct[i].networkRep, 200);

这就是我声明2d数组的方式:

int** declareMatrix(int **mymatrix, int rows, int columns)
{
    mymatrix = (int**) malloc(rows*sizeof(int*));
    if (mymatrix==NULL)
        printf("Error allocating memory!\n");
    int i,j;
    for (i = 0; i < rows; i++)
        mymatrix[i] = (int*) malloc(columns*sizeof(int));

    for(i=0; i<rows; i++){
        for(j=0; j<columns; j++){
            mymatrix[i][j] = 0;
        }
    }
    return mymatrix;
}

这就是我释放2d数组的方式:

void freeMatrix(int **matrix, int rows)
{
    int i;
    for (i = 0; i < rows; i++){
        free(matrix[i]);
    }
    free(matrix);
    matrix = NULL;
}

我所看到的奇怪的行为是,当我编译并运行我的程序时,一切看起来都不错。 但是当我将stdout传输到txt文件时,我遇到了一个seg错误。 但是,如果我注释掉包含“freeMatrix”调用的循环,则不会发生seg错误。 我究竟做错了什么?

我没有在免费代码中看到任何问题,除了, freeMatrix被调用100次,而你的分配只有1

所以,要么分配如下:

 for(int i=0; i<100; i++) //Notice looping over 100 elements. 
    astruct[i].networkRep = declareMatrix(astruct[i].networkRep, 200, 200);

或者,只为您在原始代码中分配的第0个元素免费。

freeMatrix(astruct[0].networkRep, 200);

旁注:初始化您的astruct array

mystruct astruct[100] = {};
struct myStruct astruct[100];

astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);

// do stuff...
int i;
for(i=0; i<100; i++)
    freeMatrix(astruct[i].networkRep, 200);

你分配了一个astruct但是释放了100个; 如果任何99个额外的不是NULL,那么会崩溃,这可能在你进行重定向时发生。 (由于astruct在堆栈中,它将包含那里留下的任何内容。)

其他事宜:

您使用的是数字文字而不是清单常量...定义NUMROWS和NUMCOLS并一致地使用它们。

摆脱declareMatrix的第一个参数...你传递一个值但从不使用它。

在freeMatrix中,

matrix = NULL;

什么也没做。 启用优化后,编译器甚至不会生成任何代码。

if (mymatrix==NULL)
    printf("Error allocating memory!\n");

您应该在出错时退出(1),否则您的程序将崩溃,您甚至可能看不到错误消息,因为a)stdout被缓冲并且b)您将其重定向到文件。 这也是将错误消息写入stderr而不是stdout的原因。

astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200); 

你没有传递指针的地址。 它只是将内存中的值传递给不需要的函数。

你唯一初始化struct的第一个变量,但是当你试图释放内存时,你正在分配尚未分配的内存(astruct [1],依此类推,直到100)。

当您使用malloc时,它实际上分配的内存比您指定的多一点。 额外内存用于存储诸如块大小之类的信息,以及指向下一个空闲/已使用块的链接,有时还有一些保护数据可帮助系统检测是否写入了已分配块的末尾。

如果传入不同的地址,它将访问包含垃圾的内存,因此其行为未定义(但最常见的是导致崩溃)

索引和计数无符号整数类型就足够了。 size_t是这种选择的类型,因为它保证足够大以解决/索引目标机器上的内存/数组元素的每个字节。

struct mystruct
{
  size_t mySize;
  int ** networkRep;
};

始终正确初始化变量:

struct myStruct astruct[100] = {0};

分配器的几个问题:

  • 给它一个返回特定错误代码的机会。 这通常通过使用函数返回值进行设置来完成。
  • 使用size_t作为计数器和指示和大小(“行”,“列”)(为什么请参见上文)。
  • 做适当的错误检查。
  • 清理以防工作期间发生错误。
  • 不要malloc()返回的值,因为在C中没有必要,不推荐使用
  • 使用perror()来记录错误,因为它从操作系统中获得了关于as possibe的最多信息。

有可能做到这一点:

int declareMatrix(int *** pmymatrix, size_t rows, size_t columns)
{
    int result = 0; /* Be optimistc. */

    assert(NULL != pmatrix);

    *pmymatrix = malloc(rows * sizeof(**pmymatrix));
    if (NULL == *pmymatrix)
    {
      perror("malloc() failed");
      result = -1;

      goto lblExit;
    }

    { 
      size_t i, j;
      for (i = 0; i < rows; i++)
      {
        (*pmymatrix)[i] = malloc(columns * sizeof(***pmymatrix));
        if (NULL ==   (*pmymatrix)[i])
        {
          perror("malloc() failed");
          freeMatrix(pmymatrix); /* Clean up. */
          result = -1;

          goto lblExit;
        }

        for(i = 0; i < rows; ++i)
        {
          for(j = 0; j < columns; ++j)
          {
            (*pmymatrix)[i][j] = 0;
          }
        }
      }
    }

lblExit:
    return 0;
}

解除分配器的两个问题:

  • 标记它的工作就像正确地去启动指针一样。
  • 在对其进行操作之前执行输入验证。

有可能做到这一点:

void freeMatrix(int *** pmatrix, size_t rows)
{
  if (NULL != pmatrix)
  {
    if (NULL != *pmatrix)
    {
      size_t i;
      for (i = 0; i < rows; ++i)
      {
        free((*pmatrix)[i]);
      }
    }

    free(*pmatrix);
    *pmatrix = NULL;
  }
}

然后使用这样的东西:

struct myStruct astruct[100] = {0};

...

int result = declareMatrix(&astruct[0].networkRep, 200, 200);
if (0 != result)
{
  fprintf("declareMatrix() failed.\n");
}
else
{
// Note: Arriving here has only the 1st element of astruct initialised! */
// do stuff...
}

{
  size_t i;
  for(i = 0; i < 100; ++i)
  {
    freeMatrix(&astruct[i].networkRep, 200);
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM