【问题标题】:Segmentation Core dumped分割核心转储
【发布时间】:2017-08-13 22:52:17
【问题描述】:
| |0|1|2|3|4|5|6|7|8|9|
|0| | | | | | | | | | |
|1| | | | | | | | | | |
|2| | | | | | | | | | |
|3| | | | | | | | | | |
|4| | | | | | | | | | |
|5| | | | | | | | | | |
|6| | | | | | | | | | |
|7| | | | | | | | | | |
|8| | | | | | | | | | |
|9| | | | | | | | | | |

我正在尝试制作一个看起来像这样的网格。目前,每当我尝试运行可执行文件时,我都会不断转储分段错误核心。编译器也没有显示任何错误。我也不知道如何在网格内打印数字。下面是我目前拥有的代码(只是整个作业的一部分)。非常感谢任何帮助。

void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player)
{
    /* TODO */
    int i,j;
    char grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2];
    for(i = 0; i < BOARD_HEIGHT; i++)
    {
        for(j = 0; j < BOARD_WIDTH; j++)
        {
            grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2] = '|';
            printf("%c", grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2]);
            printf("%s", EMPTY_OUTPUT);
        }
        printf("\n");
    }    
}

BOARD_HEIGHT 和 BOARD_WIDTH 是在头文件中定义的变量。

#ifndef BOARD_H
#define BOARD_H

#include "helpers.h"
#include "player.h"

#define BOARD_WIDTH 10
#define BOARD_HEIGHT 10

typedef enum cell
{
    EMPTY,
    BLOCKED,
    PLAYER
} Cell;

#define EMPTY_OUTPUT " "
#define BLOCKED_OUTPUT "*"

Cell BOARD_1[BOARD_HEIGHT][BOARD_WIDTH];
Cell BOARD_2[BOARD_HEIGHT][BOARD_WIDTH];

typedef enum playerMove
{
    PLAYER_MOVED,
    CELL_BLOCKED,
    OUTSIDE_BOUNDS
} PlayerMove;


void initialiseBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH]);

void loadBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH],
               Cell boardToLoad[BOARD_HEIGHT][BOARD_WIDTH]);

Boolean placePlayer(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Position position);

PlayerMove movePlayerForward(Cell board[BOARD_HEIGHT][BOARD_WIDTH],
                         Player * player);

void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player);

#endif

第二部分在头文件中。

完整的代码可以在这里找到a1

【问题讨论】:

  • 你能显示完整的代码吗?
  • grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2] 超出范围。
  • @aschepler,不是。 OP 需要显示更多代码。 Seg 故障发生在其他地方。
  • 您缺少输出数字的代码部分,并且您没有使用传入的 Board 数组,而是使用未初始化的网格数组。不需要使用网格数组,也不需要存储'|'数组中的字符,只需根据需要打印出行,但不要存储它们。最后也是最重要的一点,你应该使用 i 和 j 来索引数组,而不是像 BOARD_HEIGHT 和 BOARD_WIDTH 这样的常量,因为在编写时你输出了 grid[12][12] 144 次。
  • 您缺少 player.h 和 helper.h。您应该将您的问题缩减为编译和重现问题的最小代码片段。当我运行您的代码时,在添加了一些缺失的代码(我必须弥补)之后,它运行时没有出现段错误。这表明需要提供一个可以自行编译的完整示例,并演示该问题。当我们必须添加自己的代码时,它通常可以正常工作。 :)

标签: c segmentation-fault printf


【解决方案1】:

您的错误出现在您索引网格超出数组末尾的行:

grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2] = '|'; // Bug

这一行超出了本地定义的网格数组的末尾:

char grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2];

请注意,grid[][] 的有效索引从 0 到 BOARD_HEIGHT+1,从 0 到 BOARD_WIDTH+1。您的代码在这两个维度上都可以访问。

这会导致堆栈损坏,因此当 displayBoard 函数返回时,它已损坏堆栈并且您会遇到分段错误。删除此行可消除 seg 错误,但代码仍需正常工作。

您应该引用板数组,并使用索引 i 和 j,而不是硬编码的常量。

这是一个工作版本,我索引板数组,将当前单元格值存储在 currentCell 中,然后根据 switch 语句显示它。给定一个用零填充的空板,这将产生以下输出:

scott> gcc -g -ogeraldTest -O0 board.c
scott> geraldTest 
| |0|1|2|3|4|5|6|7|8|9|
|0| | | | | | | | | | |
|1| | | | | | | | | | |
|2| | | | | | | | | | |
|3| | | | | | | | | | |
|4| | | | | | | | | | |
|5| | | | | | | | | | |
|6| | | | | | | | | | |
|7| | | | | | | | | | |
|8| | | | | | | | | | |
|9| | | | | | | | | | |

这是 main() 和 printBoard 的代码,都在 board.c 中。请注意,printBoard 是按值传递板的,但最好通过引用传递它。

    #include <stdio.h>
    #include "board.h"

    void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player)
    {
        int i,j;

        // First display the header at the top.
        printf("| |");
        for(j=0; j<BOARD_WIDTH;j++)
           printf("%d|",j);
        printf("\n");

        for(i = 0; i < BOARD_HEIGHT; i++)
        {
         // Display each row number
         printf("|%d|",i);

        for(j = 0; j < BOARD_WIDTH; j++)
        {
            // Bug: grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2] = '|';
            Cell currentCell = board[i][j];

            switch(currentCell) {
               case BLOCKED:
                  printf("%s",BLOCKED_OUTPUT);
                  break;
               case PLAYER:
                  printf("P");
                  break;
               default:
                  printf("%s",EMPTY_OUTPUT);
                  break;
            }
            printf("|");

            // This code is wrong
            // printf("%c|", grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2]);
            // printf("%s", EMPTY_OUTPUT);
        }
        printf("\n");
    }
}

    int main(int argc, char ** argv)
    {
      Cell myBoard[BOARD_HEIGHT][BOARD_WIDTH] = {0};
      Player bob = 0;

      displayBoard(myBoard, &bob);
    }

我拿走了你的 board.h 并定义了缺失的类型,以便让它编译。您可以按原样使用自己的标题。

#ifndef BOARD_H
#define BOARD_H

// #include "helpers.h"
// #include "player.h"

#define BOARD_WIDTH 10
#define BOARD_HEIGHT 10

typedef int  Boolean; // Added
typedef int  Player;  // Added
typedef struct {      // Added
          int row;
          int col;
        } Position;

typedef enum cell
{
    EMPTY,
    BLOCKED,
    PLAYER
} Cell;

#define EMPTY_OUTPUT " "
#define BLOCKED_OUTPUT "*"

Cell BOARD_1[BOARD_HEIGHT][BOARD_WIDTH];
Cell BOARD_2[BOARD_HEIGHT][BOARD_WIDTH];

typedef enum playerMove
{
    PLAYER_MOVED,
    CELL_BLOCKED,
    OUTSIDE_BOUNDS
} PlayerMove;


void initialiseBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH]);

void loadBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH],
               Cell boardToLoad[BOARD_HEIGHT][BOARD_WIDTH]);

Boolean placePlayer(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Position position);

PlayerMove movePlayerForward(Cell board[BOARD_HEIGHT][BOARD_WIDTH],
                         Player * player);

void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player);
#endif

【讨论】:

  • 为了将来参考,这不需要[并且不应该]是一个单独的答案。由于您已经发布了一个,因此编辑您的旧答案并附加 [文本] 这将是可行的方法。答案通常像您的第一个一样开始,然后可能会被编辑多次[添加大量文本]。除非有特殊原因(例如,您要给出的答案将超过答案的 30,000 个字符限制),否则通常不赞成来自同一响应者的多个答案。这就是为什么当您尝试添加第二个答案时,您会收到一条提醒和“您确定要这样做吗?”。
  • 好的,感谢@CraigEstey 的提示,我将一个答案附加到另一个答案,并删除了第二个。我是 StackOverflow 的新手,所以感谢您的建议。谢谢。
猜你喜欢
  • 2020-09-24
  • 2021-08-23
  • 2015-06-25
  • 2021-06-03
  • 2011-05-19
  • 2014-01-03
相关资源
最近更新 更多