繁体   English   中英

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

[英]My first C program - Game of Life: printf segmentation fault

我的第一个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

所以,有些事情我没有。 首先,为什么我可以访问world [i] [j]但printf无法访问? 因为两个索引值都仍为0,所以它不能只是出界错误,对吗?

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

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

我敢肯定,对于某些人来说,这是令人讨厌的简单问题,请耐心等待。 我来自Java背景,因此C是可识别的,但又足以使我失望。 另外,如果需要更多信息,我可以提供。

问题可能在以下几行:

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

事实是, printf的原型是:

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

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

如果您的编译器未对这种用法提出警告,则应真正添加all-warnings-on编译器选项(例如,在GCC中为-Wall )。

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

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

关于您的问题:

首先,为什么我可以访问world [i] [j]但printf无法访问? 因为两个索引值都仍为0,所以它不能只是出界错误,对吗?

调试器print与功能printf不相关。 调试器知道类型化表达式的声明类型。 printf没有。 这就是格式字符串的用途。

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

不知道。 您正在进行段故障隔离,因此堆栈中的变量可能已损坏或其他原因。

最后,数组的大小是怎么回事? 应该是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`。

主要问题是您不能使用来打印单个字符

printf(world[i][j])

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

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

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

函数printf像这样:

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

但是您使用:

printf(world[i][j]);

您是要这样做吗?

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

另外,这是错误的:

printf(cycles);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM