Ошибка ошибки сегментации (сброс ядра), но программа работает нормально

#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 операционной системы, или, если бы это произошло, результирующее альтернативное поведение было бы лучше.