【问题标题】:Why am I getting a seg fault (multidimensional arrays C)为什么我会出现段错误(多维数组 C)
【发布时间】:2012-02-01 20:12:06
【问题描述】:

我似乎无法弄清楚我做错了什么。

int main(int argc, char **argv) {
  int height = 4, width = 6;
  int **map;
  map = (int **)(malloc(height * sizeof(int*)));
  for(i = 0; i < height; i++) {
    map[i] = (int *)(malloc(width * sizeof(int)));
  }
  fill_map(&map, height, width);
}

void fill_map(int ***map, int height, int width) {
  int i, k, character;
  for(i = 0; i < height; i++) {
    k = 0;
    while((character = getchar()) != '\n') {
        *map[i][k] = character;
        k++;
    }
  }
}

我在内部 while 循环中的 fill_map 中遇到了段错误,为什么?

【问题讨论】:

  • 提高编译器的警告级别,并注意警告
  • 编译器警告对这个问题没有多大帮助 - 我没有收到来自 GCC 的 -Wall -Wextra 或来自 MSVC 的 -Wall -W4 的有用警告。

标签: c arrays multidimensional-array segmentation-fault


【解决方案1】:

不要将 &map 发送给函数,将原型更改为接收 (int **map) 或使用 (*map)[i][k]。这是因为间接运算符 * 的优先级低于 [] 运算符。

【讨论】:

  • 您可能想添加一两句话说明为什么*map[i][k] 会导致崩溃。
  • 另外,即使在修复map访问表达式之后,如果输入的行太长,程序仍然容易崩溃。
【解决方案2】:

你希望如何结束你的 while 循环,你有没有在你的数组中保留一个“\n”?您刚刚分配了内存并试图遍历它。它永远不会找到 "\n" ,因此 while 循环会超出内存位置并且您会遇到分段错误。

【讨论】:

    【解决方案3】:

    我会使用 gdb 或其他调试器。用调试符号编译程序,在其中运行它,它会告诉你在哪一行出现了段错误。

    【讨论】:

      【解决方案4】:

      首先——听从 'prmg' 和 'perreal' 的建议。

      不要强制转换 malloc 的返回值。 malloc 返回一个 void * 并且强制转换是不必要的。如果您忘记#include &lt;stdlib.h&gt;,那您就是在自找麻烦。

      map = malloc( height * sizeof *map );
      

      【讨论】:

        【解决方案5】:

        您使用的不是二维数组,而是它的模拟。在现代 C 中,从 C99 开始,使用“可变修改类型”,您的任务就像这样简单:

        #include <stddef.h>
        #include <stdlib.h>
        #include <stdio.h>
        
        void fill_map(size_t height, size_t width, char map[height][width]) {
          int character;
          for(size_t i = 0; i < height; i++) {
            for (size_t k = 0; k < width; k++) {
              if ((character = getchar()) != '\n')
                map[i][k] = character;
              else break;
            }
          }
        }
        
        int main(int argc, char **argv) {
          size_t height = 4, width = 6;
          char (*map)[width] = malloc(sizeof(char[height][width]));
          fill_map(height, width, map);
        }
        
        • 先传递矩阵维度,然后你可以简单地在矩阵参数的声明中使用它们
        • 使用size_t 进行索引
        • 不要强制返回 malloc
        • 小心循环的边界
        • 还可以更好地检查文件结尾(作业)

        【讨论】:

          【解决方案6】:

          您的分段错误来自您错误地取消引用 map 的事实;你应该把它写成(*map)[i][k]而不是*map[i][k]。虽然最好在对fill_map 的调用中去掉&amp; 并相应地调整原型:

          fill_map(map, height, width);
          ...
          void fill_map(int **map, int height, int width)
          {
            ...
            map[i][k] = character;
            ...
          }
          

          您可以像这样清理您的 malloc 调用:

          map = malloc(height * sizeof *map);
          

          map[i] = malloc(width * sizeof *map[i]);
          

          强制转换在 C1 中不是必需的,被认为是不好的做法。


          1 这在 C++ 中不是正确的;需要强制转换,但如果您正在编写 C++,则应该使用 new 而不是 malloc

          【讨论】:

            猜你喜欢
            • 2020-05-26
            • 2013-02-11
            • 2020-09-05
            • 1970-01-01
            • 1970-01-01
            • 2018-01-07
            • 1970-01-01
            • 2011-04-23
            相关资源
            最近更新 更多