来自2d阵列分配的seg故障

时间:2013-02-12 06:45:52

标签: c pointers malloc

我有一个结构“单元格”定义为

typedef struct{
int id;
terrainType terrain;
} cell;
然后我用

制作一个2d的单元格数组
cell** makeCellGrid(int sizeX, int sizeY)
{  
    cell** theArray;  
    int i;

    theArray = (cell**) malloc(sizeX*sizeof(cell*));  

    for ( i = 0; i < sizeX; i++)
    {
        theArray[i] = (cell*) malloc(sizeY*sizeof(cell));  
    }

   return theArray;  
}  

起初我认为这个工作正常,但是稍后我发现有一些值(例如makeCellGrid(32,87))它会中断。 我很新鲜的C指针和记忆垃圾,并希望有人可以指出我在正确的方向。

数字范围较小我没有问题

访问它
map[i][j].id = x;

等等

编辑:忘了在测试中添加来自

的seg错误
theArray[i] = (cell*) malloc(sizeY*sizeof(cell)); 

1 个答案:

答案 0 :(得分:3)

代码缺少malloc()系统调用的错误检查。

因此,如果对malloc()的第一次调用失败,第二次调用(在循环中)会尝试将内存分配给NULL,这确实会导致您正在目击的分段违规。

您可以考虑修改代码,如下所示:

#include <stdlib.h>

typedef struct {
  int id;
  TerrainType terrain;
} CellType;

void freeCellGrid(CellType ** ppCells, size_t sizeX)
{
  size_t i = 0;
  for (; i < sizeX; ++i)
  {
    free(ppCells[i]);
  }

  free(ppCells);
}

CellType ** makeCellGrid(size_t sizeX, size_t sizeY)
{  
    CellType ** ppCells = malloc(sizeX * sizeof(*ppCells));  

    if (ppCells)
    {
      size_t i = 0;

      for (; i < sizeX; ++i)
      {
          ppCells[i] = malloc(sizeY * sizeof(**ppCells));  
          if (NULL == ppCells[i])
          {
            freeCellGrid(ppCells, i);
            ppCells = NULL;

            break;
          }
      }
   }

   return ppCells;  
} 

关于我的修改的说明:

  • 始终检查系统调用是否有错误(如果返回错误malloc(),则NULL
  • 最好使用unsigned类型来访问内存/数组指示; size_t适用于此
  • 在C中,无需转换void *函数返回的值,如malloc()
  • 始终尝试尽快初始化变量;未启动的变量很容易导致应用程序的“非理性”行为
  • 如果使用指针,将间接级别“编码”到其名称中可能会有所帮助(我在这里通过使用前缀pp来表示它是一个2级间接)
  • 类型与变量不同:区分这种情况的一种方法是使用大写字母(CellType)和使用小写字母的变量(ppCells)启动类型名称。
  • 如果将内存分配给指针并且重要的是分配的内存的大小有些适合指针的类型,那么使用(解除引用的)指针本身作为sizeof运算符的参数然后某种类型总是更安全。由于在开发过程中可能会更改分配内存的指针的声明,并且将忘记调整malloc()的参数。简而言之:按照我的方式做的不那么容易出错。
  • 如果封装动态创建的结构(包括数组),也可以实现一个解除分配的方法(这里:freeCellGrid())。首先对这个解除分配器进行编码更好的开始,然后在编码分配器的错误处理时手动编写(如第二次调用malloc()所示)。