我的第一个C程序 - 生命游戏:printf分段错误

时间:2017-01-17 22:18:30

标签: c

我遇到了我的第一个C程序的问题,这是Conway的C / C ++课程的生命游戏版本。我写了它,然后用GCC编译它,但是我试图追逐分段错误。具体来说,现在我的问题在于我的打印功能。我也包括main()以防问题与之相关。我遗漏了其他功能,因为我看不出它们是如何相关的。

#include <stdio.h>
#define  XMAX  240
#define  YMAX  80

int main(int argc, char **argv) {

  int cycles  = 0;
  char current[XMAX][YMAX];
  char next[XMAX][YMAX];
  //first, fill current with all spaces
  int i,j;
    for( j=0; j< YMAX; j++){
      for( i = 0; i < XMAX; i++) {
        current[i][j] = ' ';
    }
  }
  //next, check if there are an even number of inputs
  //if there are, edit those cells in current
  if (argc > 1) {
    if (argc % 2 != 0) {
     int k;
     for(k = 0; k < argc-1; k+=2) {
     current[atoi(*argv[k])][atoi(*argv[k+1])] = 'O';
  }
 }

  //otherwise, we print an error message and quit.-
   else {
    printf("Invalid number of command line arguments, must be even");
    return;
}
}
//print starting configuration
  print(current, cycles);
//start recursive update method
  update(current, next, cycles);
}

违规打印功能:

// method that prints world and number of cycles
void print(char world[XMAX][YMAX], int cycles) {
printf(cycles);
printf("\n");
// iterates through world printing everything
int i;
int j;
for( j = 0; j < YMAX; j++) {
  for( i = 0; i < XMAX; i++) {
    printf(world[i][j]);
    }
  //print a new line every time we jump down a row
  printf("\n");
  }
}

这是调试日志。这在发生任何输出之前发生。

Program received signal
SIGSEGV, Segmentation fault.
0x00007ffff7aa32ba in strchrnul () from /lib64/libc.so.6
(gdb) backtrace
#0  0x00007ffff7aa32ba in strchrnul () from /lib64/libc.so.6
#1  0x00007ffff7a59cd2 in vfprintf () from /lib64/libc.so.6
#2  0x00007ffff7a64519 in printf () from /lib64/libc.so.6
#3  0x000000000040092b in print (world=0x7fffffff9210, cycles=0) at game.c:48
#4  0x000000000040088b in main (argc=1, argv=0x7fffffffde18) at game.c:34
(gdb) frame 3
#3  0x000000000040092b in print (world=0x7fffffff9210, cycles=0) at game.c:48
48            printf(world[i][j])  ;
(gdb) print i
$1 = 0
(gdb) print j
$2 = 0 
(gdb) print world[i][j]
$3 = -128 '\200'
(gdb) print sizeof(world)
$4 = 8 
(gdb) print sizeof(world[0])
$5 = 80

所以,有一些我没有得到的东西。首先,为什么我可以访问世界[i] [j]但printf不能?它不仅仅是一个越界错误,因为两个索引值仍然是0,对吗?

其次,-128'\ 200'表示什么,为什么它不是空格字符? Main应该用空格填充数组,所以我可能搞乱了。

最后,数组的大小是怎么回事?它应该是240 x 80,所以为什么一个尺寸80但另一个只有8?

对于你们中的一些人,我确信这些是令人作呕的简单问题,所以请耐心等待。我来自一个java背景,所以C是可识别的,但只是不同,足以让我失望。此外,如果需要更多信息,我可以提供。

3 个答案:

答案 0 :(得分:3)

问题很可能在以下几个方面:

printf(cycles);
printf(world[i][j]);

问题是printf的原型是:

int printf(const char *format, ...)

但您传递intchar作为单个参数,而不是const char *。这应该在编译时发出警告。永远不要忽视警告!

如果您的编译器没有警告这种用法,您应该在GCC中添加all-warnings-on编译器选项(-Wall)。

解决方案很简单,使用格式字符串:

printf("%d\n", cycles); // add the \n to the same format!
printf("%c", world[i][j]);

关于您的问题:

  

首先,为什么我可以访问世界[i] [j]但是printf不能?它不能只是一个越界错误,因为两个索引值仍然是0,对吗?

调试器print与函数printf无关。调试器知道类型化表达式的声明类型; printf没有。这就是格式字符串的用途。

  

其次,-128'\ 200'表示什么,为什么它不是空格字符? Main应该用空格填充数组,所以我可能搞乱了。

不知道。你是segfaulting,所以堆栈中的变量可能已损坏或其他。

  

最后,数组的大小是怎么回事?它应该是240 x 80,所以为什么一个尺寸80但另一个只有8?

函数内部的

world实际上不是数组,而是指针。函数参数中的数组声明被降级为指针,因此char world[XMAX][YMAX]被编译为char (*world)[YMAX]。因此,sizeof(world)是指针的大小。但是,由于它是指向数组的指针,world[0]的类型为char[YMAX], so sizeof(world [0])is YMAX`。

答案 1 :(得分:1)

主要问题是您无法使用

打印单个字符
printf(world[i][j])

因为第一个参数必须是一个字符串。所以它试图将world [i] [j]解释为字符串并搜索第一个字节为0(C中的字符串终止符),因此继续搜索不允许访问的内存区域(因此是段错误)

如果您只想打印一个字符,请使用

print("%c",world[i][j])

答案 2 :(得分:0)

函数printf是这样的:

int printf ( const char * format, ... );

但你使用:

printf(world[i][j]);

你的意思是这样做:

printf("%d", world[i][j]);

另外,这是错误的:

printf(cycles);