2011-08-15 44 views
3

我正在寫一個帶有ncurses的小型控制檯遊戲(作爲學習任務),並且我已經有一些小問題了(這是我第一次使用列表在C),但從來沒有一個真正的showstopper。然而,作爲「未來規定」,我想實現一個基本的調試日誌文件。而這正是事情開始表現奇怪的地方。fprintf由於突然地址更改導致段錯誤

日誌文件是全局聲明的,fopen()(使用w +模式)和ferror()不顯示任何錯誤證據。相反,一切似乎完美地工作,日誌文件被創建,信息被寫入它。然而,在我爲各種函數添加了一些調試輸出之後,遊戲只是段錯誤。作爲consquence,我已經註釋掉幾乎所有調試輸出到文件,現在這個簡單的代碼行崩潰了整場比賽:

fprintf(debuglog, "loop_game()\n\tTime's over! Returning 0\n"); 

我用gdb運行程序,並BT全輸出如下:

#0 0x00007ffff7886f24 in fwrite() from /lib/libc.so.6 
No symbol table info available. 
#1 0x000000000040224f in loop_game (pl=0x62d800, list_win=0x62f930, 
    timer=0x632620, list_ob=0x632640) at game.c:207 
     elapsed = 60 
#2 0x0000000000402d53 in main() at main.c:62 
     pl = 0x62d800 
     list_win = 0x62f930 
     timer = 0x632620 
     list_ob = 0x632640 

(game.c:207是我前面提到的線)。此外,有人告訴我,我應該使用手錶DEBUGLOG,其輸出是如下:

Old value = (FILE *) 0x0 
New value = (FILE *) 0x62f6f0 
init() at console.c:128 
128  fprintf(debuglog, "init()\n\tInitialised ncurses\n"); 

然後我使用繼續,大約10秒之後,它打印出這些行:

Old value = (FILE *) 0x62f6f0             
New value = (FILE *) 0x20062f6f0            
move_obstacle (win_game=0x62f970, target_ob=0x63ce00) at game.c:370    
370    wrefresh(win_game);  

然後,在60秒之後(這是時間後遊戲應該正常結束) ,遊戲segfaults。有時觀察點用gdb與DEBUGLOG時它也輸出

Old value = (FILE *) 0x22f6f0 
New value = (FILE *) 0x0 

0X2而不是爲0x0。我甚至已經有了一個SIGABRT。

由於我是初學者,我不知道下一步該怎麼做。我已經問過一些確實有廣博知識的人,但他們無法找到「萬惡之源」。如果你需要的代碼,你可以找到它here。我希望這只是我犯的一個愚蠢的錯誤...

回答

8

這很可能是你寫的。這是我的意思。

console.c,你有

int field[FIELDMAXX][FIELDMAXY]; 
FILE * debuglog; 

在改變debuglog行你必須:

field[target_ob->x_pos][target_ob->y_pos] = OBSTACLE; /* Changes debuglog. */ 

所以這是非常有可能的值target_ob->x_postarget_ob->y_pos是你不期待着什麼。

現在,您需要做的第一件事是修復(找出與這些座標發生了什麼)。你可以做的第二件事是定義一些其他記錄方式。我個人認爲我會使用一個單獨的日誌記錄功能(這將調用vfprintf),我會使debugfile靜態某些文件。

+1

單字節被覆蓋的可能性更大。請注意,'debuglog'的值從'0x00062f6f0'變爲'0x20062f6f0'。 (0x20是ASCII空格字符的事實*可能是線索。) –

+0

...我找到了一個解決方案,只要我被允許這樣做,我就會發布它:) –

0

所以,我找到了一個解決方案。它一個愚蠢的錯誤我犯了...真是愚蠢:d

比賽場地由int field[FIELDMAXX][FIELDMAXY];,其中FIELDMAXX是78和FIELDMAXY是21.現在看看create_obstacle()宣佈:爲座標新創建的障礙是FIELDMAXX + 1get_randypos()(它返回從1到21的整數)。在這裏,它是典型的初學者的錯誤:在move_obstacle(),有一行說field[target_ob->x_pos][target_ob->y_pos] = OBSTACLE;(OBSTACLE被定義爲2)。

每個障礙物每隔一個「長度單位」向左移動(target_ob->x_pos--;)。所以,如果有x_pos = 79新創建的障礙(這是FIELDMAXX + 1)和y_pos = 21move_obstacle()移動,其新x_pos是(而其y_pos是)。結果,我上面提到的這條線試圖將field[78][21]設置爲​​- 這是不可能的(超出界限)。我現在感到有點慚愧:)