fprintf вызывает ошибку сегментации из-за внезапного изменения адреса - PullRequest
3 голосов
/ 16 августа 2011

Я пишу небольшую консольную игру с 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 секунд (это время после того, как игра должна нормально закончиться), игра перестает работать.Иногда при использовании gdb с debuglog в качестве точки наблюдения он также выводит

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

или 0x2 вместо 0x0.У меня даже был SIGABRT.

Поскольку я новичок, я понятия не имею, что делать дальше.Я уже спросил некоторых ребят, которые, безусловно, обладают обширными знаниями, но они не смогли найти «корень зла»Если вам нужен код, вы можете найти его здесь .Надеюсь, это просто глупая ошибка, которую я совершил ...

Ответы [ 2 ]

8 голосов
/ 16 августа 2011

Скорее всего, вы пишете поверх этого.Вот что я имею в виду.

В console.c у вас есть

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

В строке, которая меняется debuglog у вас есть:

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

Так что это довольноскорее всего, значения target_ob->x_pos и target_ob->y_pos - это то, чего вы не ожидаете.

Теперь первое, что вам нужно сделать, это исправить это ( выяснить, что происходит с этими координатами ).Второе, что вы можете сделать, это определить какой-то другой способ ведения журнала.Лично я думаю, что я бы использовал отдельные функции ведения журнала (которые вызвали бы vfprintf), и я бы сделал debugfile статическим для какого-то файла.

0 голосов
/ 16 августа 2011

Итак, я нашел решение.И это было глупой ошибкой, которую я сделал ... действительно глупо: D

Игровое поле объявлено int field[FIELDMAXX][FIELDMAXY];, где FIELDMAXX равно 78, а FIELDMAXY равно21. Теперь взгляните на create_obstacle(): координаты для вновь созданных препятствий: FIELDMAXX + 1 и get_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_pos равно 78 (в то время как его y_pos равно 21 ).И как следствие, строка, о которой я упоминал выше, пытается установить field[78][21] на OBSTACLE - и это невозможно (за пределами).Теперь мне немного стыдно за себя:)

...