#c #file #segmentation-fault
#c #файл #ошибка сегментации
Вопрос:
Моя цель — вывести строки файла без комментариев на экран или в выходной файл, как указано. Мой код работает нормально в обоих случаях (т. Е. Я получаю желаемый результат) Однако, когда я печатаю строки на экране, все работает нормально, и после распечатки всего написано Segmentation fault (core dumped)
Вот мой код:
/* Assignment 1 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#define MAXS 256
int main(int argc, char *argv[])
{
FILE *fp;
FILE *op;
char line[MAXS] = {0};
int max_x, max_y, num_pt, rand_inst;
int ch;
int inputfile = 0, outputfile = 0;
int i;
for (i = 1; i < argc; i )
{
if (strcmp (argv[i], "-i") == 0)
inputfile = i 1;
if (strcmp (argv[i], "-o") == 0)
outputfile = i 1;
}
if (inputfile == 0)
{
/* invalid command line options */
printf("nIncorrect command-line...n");
printf("> %s [-i inputfile [-o outputfile]]nn", argv[0]);
exit(0);
}
fp = fopen(argv[inputfile], "r");
if (fp == 0)
{
printf("nCould not find %sn", argv[inputfile]);
exit(0);
}
/* while ((ch = fgetc(fp)) != EOF)) */
/* This part is where I get the error but I get the desired output */
if (outputfile == 0)
{
while (fgets (line, MAXS, fp) != NULL)
{
char *p = line;
size_t len = strlen (line);
while (len > 0 amp;amp; (line[len-1] == 'n' || line[len-1] == 'r'))
line[--len] = 0; /* strip newline or carriage rtn */
while (isspace (*p)) /* advance to first non-whitespace */
p ;
/* skip lines beginning with '#' or blank lines */
if (*p == '#' || !*p)
continue;
printf("%sn", line);
}
}
else
{
op = fopen(argv[outputfile], "w");
while (fgets (line, MAXS, fp) != NULL)
{
char *p = line;
size_t len = strlen (line);
while (len > 0 amp;amp; (line[len-1] == 'n' || line[len-1] == 'r'))
line[--len] = 0; /* strip newline or carriage rtn */
while (isspace (*p)) /* advance to first non-whitespace */
p ;
/* skip lines beginning with '#' or blank lines */
if (*p == '#' || !*p)
continue;
fprintf(op, "%sn", line);
}
}
fclose(op);
return 0;
}
Вот результат, который выдает ошибку сегментации:
100 100
10
0 0
0 90
70 100
100 50
30 30
30 70
70 70
70 30
50 50
45 0
Ошибка сегментации (сброс ядра)
Однако приведенное выше является желаемым результатом за вычетом ошибки ошибки сегментации
Я знаю, что ошибка сегментации связана с чтением / записью в недопустимую ячейку памяти, но я не могу понять, почему программа выдает мне ошибку при условии, что у меня нет ошибок компиляции, и я получаю желаемый результат
Язык: c99; Компилятор: gcc
Комментарии:
1. Используйте отладчик. Как минимум, он сразу сообщит вам, какая строка вызывает ошибку seg (и многое другое). Я предполагаю, что это строка:
if (*p == '#' || !*p)
. Нет никаких проверок, чтобы убедиться, чтоp
это все еще действительный указатель (т. Е. Не Закончился конецline
буфера).2. «программа работает нормально» — преамбула к этому заявлению предполагает, что это не так. Если бы это был я, я бы начал с того, что поднял ваши уровни предупреждений до педантичных высот, а затем исправил (не скрыл) все, что помечено. Пример: какое значение
op
вы ожидаете передатьfclose(op);
в случае, когдаif
берется, а неelse
ветвь вашего подозрительного раздела (например, в случае, когда вы не указываете выходной файл)? Представленный отступ не позволяет легко увидеть, чтоfclose(op);
находится не в том месте. Она должна быть внутри закрывающейelse
фигурной скобки.3. @WhozCraig Вы были правы, я поместил свой
fclose(op)
вelse statement
и не получил ошибку.4. Обратите внимание, что у вас не должно быть двух больших повторений кода, как показано. Вы должны либо открыть файл (
op = fopen(…);
), либо использоватьstdout
(op = stdout;
), а затем использовать более общий код.
Ответ №1:
Ошибка сегментации вызвана вашей последней строкой fclose(op)
. Я подозреваю op
, что это NULL
или недопустимая ячейка памяти (т.Е. Мусор), Которая вызывает ошибку seg.
В дополнение к вставке внутри инструкции (как указано в комментариях). fclose
else
..Я бы также инициализировал эти указатели на файлы.
Комментарии:
1. Нет необходимости инициализировать указатели файлов в их объявлениях, если им присваиваются допустимые значения до того, как их значения будут использованы. В частности, нет оснований предполагать, что их инициализация предотвратила бы ошибку segfault операционной системы, или, если бы это произошло, результирующее альтернативное поведение было бы лучше.