c - 二维数组分配的段错误

标签 c pointers malloc

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

typedef struct{
int id;
terrainType terrain;
} cell;

然后我制作一个二维单元格数组
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;

等等

编辑:忘记添加,从测试中,段错误源自
theArray[i] = (cell*) malloc(sizeY*sizeof(cell)); 

最佳答案

该代码缺少对 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() 所示)。
  • 关于c - 二维数组分配的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14826958/

    相关文章:

    c - 嵌套结构分配内存

    改变二维动态数组(c中的realloc)

    c - 将目录依赖项指定为百分比规则时,Linux 上的 Make 行为非常奇怪

    c - 消息的 Adler32 + adler 总和是否为零(如 CRC32)

    c++ - 如何将 C++ 结构数组传递给 CUDA 设备?

    python - python强制创建新的内存对象

    linux - malloc() 是根据单线程还是多线程执行不同的?

    Java 字节缓冲区到 C

    c - 1. 将 N 秒捕获的数据包保存到一个 pcap 文件中 & 2. 从 Wireshark 中的程序打印输出

    C++ 对象 : When should I use pointer or reference