簡體   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