【问题标题】:fprintf causes segmentation fault due to sudden address changefprintf 由于地址突然更改而导致分段错误
【发布时间】:2011-08-15 23:25:20
【问题描述】:

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

日志文件是全局声明的,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");

然后我使用了continue,大约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。我希望这只是我犯的一个愚蠢的错误......

【问题讨论】:

    标签: c segmentation-fault printf


    【解决方案1】:

    很可能你正在写它。这就是我的意思。

    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 设置为静态到某个文件。

    【讨论】:

    • 单个字节被覆盖的可能性更大。请注意,debuglog 的值从 0x00062f6f0 更改为 0x20062f6f0。 (事实上​​ 0x20 是 ASCII 空格字符可能是一个线索。)
    • ...我找到了解决方案,我会尽快发布它:)
    【解决方案2】:

    所以,我找到了解决方案。这我犯的一个愚蠢的错误......真的很愚蠢: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 = 21的障碍物被move_obstacle()移动,它的新x_pos78(而它的y_pos21)。因此,我上面提到的那一行试图将field[78][21] 设置为OBSTACLE - 这是不可能的(越界)。我现在有点为自己感到羞耻:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 2014-07-20
      • 1970-01-01
      • 2018-12-09
      • 2018-01-02
      相关资源
      最近更新 更多