C 数组检查行和列。指针问题(取消引用 NULL 指针警告)

C Array check row and column. Issue with pointer(dereferencing NULL-Pointer warning)

我对编程还是个新手,这个网站请对我这个不知情的傻瓜好一点。我目前正在做一项任务。我们需要在 C 中制作一个 Binoxxo 拼图,并在输入值时根据规则检查它是否正确。规则是:

  1. 'x'或'o'.
  2. 后面不能超过两个
  3. 每一行和每一列都需要等量的 'x' 和 'o'.
  4. 所有行和列都是唯一的。

Binoxxo 字段是一个 array[10][10],填充有 'x'、'o' 和 ' '。对于第二条规则,我有一个可行的解决方案。但是,我真的无法弄清楚其他两个。我现在越来越习惯数组,但我想我还是不太明白。

这是我对规则 1 的处理方式:

//There can't be more than two following 'x' or 'o'
for (i = j = 0; i < 10; i++) {
    for (j = 0; j < 10; j++) {
        if ((puzzle[i][j + 1] == val) && (puzzle[i][j - 1] == val)) x++;
        if ((puzzle[i][j + 1] == val) && (puzzle[i][j + 2] == val)) x++;
        if ((puzzle[i][j - 1] == val) && (puzzle[i][j - 2] == val)) x++;
        if ((puzzle[i + 1][j] == val) && (puzzle[i - 1][j] == val)) x++;
        if ((puzzle[i + 1][j] == val) && (puzzle[i + 2][j] == val)) x++;
        if ((puzzle[i - 1][j] == val) && (puzzle[i - 2][j] == val)) x++;

        if (x > 0)
            return false;
    }
}

为了更好地理解,这是数组的图片。

我试图覆盖一个点周围的区域,以确保连续出现的 x 或 o 不会超过两个。 val通过控制台输入到另一个函数中,可以是x或o。 当我尝试 运行 时,它首先正确启动,然后我尝试输入一些内容,但出现错误 0xC0000005 Access Violation.

我了解到当指针出现问题时可能会发生此错误。我注意到我有一个警告 C6011 dereferencing NULL-Pointer,这让我想到了这个:

char** board() 
{
    int i, j;
    char** puzzle;
    char arrpuzzle[10][10] = {' ', ' ', 'o', 'x', ' ', ' ', ' ', ' ', ' ', 'o',
                            'x', ' ', ' ', 'x', ' ', ' ', ' ', ' ', ' ', ' ',
                            ' ', ' ', 'o', ' ', ' ', 'x', ' ', ' ', ' ', 'o',
                            ' ', ' ', ' ', ' ', 'o', ' ', ' ', ' ', 'o', ' ',
                            'o', ' ', ' ', 'x', ' ', ' ', ' ', 'x', ' ', ' ',
                            'o', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'o', ' ',
                            ' ', ' ', ' ', 'x', ' ', 'x', ' ', ' ', ' ', ' ',
                            ' ', 'o', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                            ' ', 'o', ' ', 'o', ' ', 'x', 'x', ' ', ' ', ' ',
                            ' ', ' ', 'x', ' ', ' ', ' ', 'o', ' ', 'x', 'o' };

    puzzle = (char**)malloc(sizeof(char*) * 10);

    for (i = 0; i < 10; i++) {
        puzzle[i] = (char*)malloc(sizeof(char) * 10); // Warning here...
        for (j = 0; j < 10; j++) {
            puzzle[i][j] = arrpuzzle[i][j];           // And here
        }
    }
    return puzzle;
}

我做错了什么?问题是由于malloc吗?我该怎么做才能解决这个问题?有人可以给我一些提示吗?

在您的规则 1 测试代码中,无条件检查相邻单元格,即使被测试的单元格位于边缘(或角落)。

在记忆中,puzzle 指向的内容看起来像这样:

...
      puzzle
------[X]------------------------------------------------------
--------\------------------------------------------------------
---------[A][B][C][D][E][F][G][H][I][J]------------------------
----------/--/--| ...                 \------------------------
---------/--/---[][][][][][][][][][]---\-----------------------
--------/--[][][][][][][][][][]---------[][][][][][][][][][]---
-------[][][][][][][][][][]------------------------------------
---------------------------------------------------------------
...

访问puzzle[i][j+1]时,如果i==2j==3,则访问地址C后的第5个字符(C+4*sizeof(char))。但是如果 j==9,那么将访问一个未定义的值(“第 11 个”- 分配的最后一个之后的 char 单元格)。这可能不会导致访问冲突,因为它可能在进程的内存范围内,但可能会导致细微且难以发现的错误。

然而,当puzzle[i+1][j]被访问时,和i==9,有一个不同的问题:地址J之后的地址单元将被视为一个地址(a char *),并取消引用。

那里存储的值可能是:

  • 某些值恰好是进程内存范围内的地址,导致细微错误。
  • 0x0,导致 NULL 取消引用。
  • 某些值超出进程的内存范围,导致访问冲突。

其他边([i-1][j-1])的问题类似。