Ошибка сегментации в файловом вводе-выводе, не удается выяснить

#file-io #segmentation-fault #c89

Вопрос:

В принципе, я переписал код, который продолжал выдавать мне ошибку сегментации (дамп ядра) при запуске, и я решил проверять каждый шаг, чтобы исключить проблемы.

Мой код работает, пока я не попытаюсь получить доступ/использовать последнюю строку данных входных файлов. Я делаю с этой строкой то же самое, что и с предыдущей строкой, но это наводит на мысль о чем-то неправильном.

Вот мой код для ввода-вывода файлов и обработки данных:

введите описание изображения здесь

Сам входной файл просто:

 20 20
10 10 u
5 5 d
 

Комментарии:

1. Просто в качестве отступления, обычная практика состоит в том, чтобы включить ваш код в сам вопрос, причем в виде текста, а не изображения. Вы хотите сделать как можно больше, чтобы нам было проще вам помочь. Учитывая вашу новизну на сайте, мы, вероятно, можем простить это один раз, но вам было бы хорошо посоветовать сделать это в будущем, чтобы ваши вопросы не закрывались без необходимости. Обычно я бы исправил это для новичков, но мне приходится переписывать слишком много кода, особенно когда вы можете просто вырезать и вставить текст намного проще.

2. Кстати, последнее мое предложение выше-это предложение о том, что вам следует сделать с этим вопросом. Не ждите следующего вопроса 🙂

3. И вы можете отформатировать код несколькими способами. Один из них состоит в том, чтобы префиксировать каждую строку кода четырьмя пробелами (больше, если вам нужны отступы). Я исправил ваш вопрос другим способом, начав блок кода с трех обратных ссылок (и языка), таких как <backtick><backtick><backtick>c , и закончив его всего тремя обратными ссылками. Эти линии обратной связи должны быть на своей собственной линии.

4. Eeknormous, поскольку вы еще не вставили код в виде текста, я думаю, что могу, по крайней мере, включить изображение в вопрос и изменить его размер, чтобы оно было читаемым, чтобы нам не нужно было переходить по ссылке, чтобы добраться до него. Однако в какой-то момент вам действительно следует заменить это текстом.

Ответ №1:

В строке 27 вы разыменовываете неинициализированное playerDirInput , что является неопределенным поведением:

 playerDir = (char)playerDirInput[0];
 

Это, вероятно, и есть причина вашей аварии. Если этот блок кода предназначен для отражения следующего, похоже, что вы просто не прочитали третий пункт в этой строке, который playerDirInput , вероятно, и должен быть взят. Это было бы что-то вроде:

 fgets(line, 8, f);

playerRowChar = strtok(line, " ");
playerRow = atoi(playerRowChar);

playerColChar = strtok(NULL, " ");    // <- fixed this, see below.
playerCol = atoi(playerColChar);

playerDirInput = strtok(NULL, " ");   // <- add this.
playerDir = (char)playerDirInput[0];
 

Тем не менее, я бы посоветовал вам вместо этого выбрать более простую sscanf версию, которая будет выглядеть примерно так (включая проверку, чтобы убедиться, что вы получите три элемента).:

 fgets(line, 8, f);
if (sscanf(line, "%d %d %c", amp;playerRow, amp;playerCol, amp;playerDir) != 3) {
    handleErrorIntelligently();
}
 

Я склонен предпочитать fgets , чтобы за мной следовали sscanf , а не fscanf . Последнее может привести к сбою таким образом, что вы не будете уверены, где заканчивается указатель входного потока. С fgets помощью этого вы всегда знаете , что прочитали строку (или можете легко обнаружить, что вы прочитали частичную строку, и скорректировать ее).


Другие потенциальные проблемы, на которые вам следует обратить внимание:

  • В строке 25 это strtok должно быть такого NULL типа, а не line . Последний просто перечитает первый пункт в этой строке, где вы хотите следующий пункт.
  • Вам действительно следует проверить функции, которые могут возвращать проблемные значения (например, NULL из strtok ). В противном случае их использование может вызвать проблемы. Это, конечно, зависит от данных, которые вы читаете, поэтому не обязательно может быть проблемой, если вы контролируете это.