fprintf会因突然地址变化而导致分段错误

时间:2011-08-15 23:25:21

标签: c segmentation-fault printf

我正在用ncurses编写一个小型控制台游戏(作为一项学习任务)并且我已经遇到了一些小问题(这是我第一次使用C中的列表),但从来没有真正的showstopper。但是,作为“未来的供应”,我想实现一个基本的调试日志文件。这就是事情开始变得奇怪的地方。

日志文件是全局声明的,fopen()(使用w +模式)和ferror()没有显示任何错误证据。相反,一切似乎完美无缺,创建了日志文件,信息被写入其中。但是,在我将一些调试输出添加到各种功能之后,游戏只是段错误。作为一个结果,我几乎将每个调试输出都注释到文件中,现在这个简单的代码行崩溃整个游戏:

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

我使用gdb运行程序, bt full 输出以下内容:

#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是我之前提到的那条线)另外,有人告诉我应该使用 watch 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秒后(这是游戏正常结束后的时间),游戏会出现段错误。有时,当使用带有 debuglog 的gdb作为观察点时,它也会输出

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

0x2 而不是0x0。我甚至已经有了一个SIGABRT。

由于我是初学者,我不知道下一步该做什么。我已经问过一些肯定有广泛知识的人,但他们无法找到“万恶之源”。如果您需要代码,可以找到它here。我希望这只是我犯下的一个愚蠢的错误......

2 个答案:

答案 0 :(得分: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 :(得分: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 = 79FIELDMAXX + 1)和y_pos = 21的新创建障碍被move_obstacle()移动,则其新x_pos 78 < / strong>(虽然其y_pos 21 )。因此,我上面提到的这一行试图将field[78][21]设置为OBSTACLE - 这是不可能的(超出范围)。我现在对自己感到有点惭愧:)。