Ошибка сегментации в программе, которая читает последние 10 строк из командной строки - PullRequest
0 голосов
/ 23 февраля 2019

В настоящее время я пытаюсь создать программу, которая печатает последние 10 строк другой текстовой программы, которая передается через командную строку.Функция read () должна прочитать одну строку из текстового файла, а затем вернуть либо строку, либо NULL, в то время как основная функция должна продолжать присваивать выходные данные read (), пока не будет присвоен NULL.

Я ушелчерез много разных версий этой программы, но это всегда приводит к ошибке сегментации.Как начать отладку ошибки сегментации?

Я включил программу ниже.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *read(){
   char *line = (char *) malloc (80 * sizeof(char));
   fgets(line,80,stdin);
   if (line != NULL) {
      line[strlen(line)-1] = '\0';
      return line;
   }
   else {
      free(line);
      return NULL;
   }
}

int main()
{
   int i=0,j,k,l;
   char **arr = (char **) malloc (100 * sizeof(char *));
   for (k = 0; k < 100; k++) {
      arr[k] = malloc (80 * sizeof(char));
   }

   while(1){
      strcpy(arr[i],read());
      if (arr[i]=NULL) break;
      i++;
      //printf("%s", arr[i]);  //DEBUG
   }

   for (l = 0; l < 100; l++){
      free(arr[l]);
   }
   free(arr);

   for (j = i-11; j < i; j++) {
      printf("%s\n", arr[j]);
   }
   printf("\n");

   return 0;
}

1 Ответ

0 голосов
/ 23 февраля 2019

в main

while(1){
  strcpy(arr[i],read());
  if (arr[i]=NULL) break;

вы никогда не выходите из цикла, потому что arr[i]=NULL не имеет оснований быть истинным из read (из-за ошибкив read ), поэтому вы пишете из arr с неопределенным поведением (ваш сбой)

Вы плохо управляете концом файла при чтении:

fgets(line,80,stdin);
if (line != NULL) {

вам нужно проверить результат fgets нет, если строка равна NULL, за исключением проверки malloc success

notчто line[strlen(line)-1] = '\0'; бесполезно, потому что fgets ставит последний нулевой символ, к счастью, как может работать strlen ?

Так что read может быть:

char *read(){
  char *line = (char *) malloc (80 * sizeof(char));

   if (line != NULL) {
     if (fgets(line,80,stdin) == NULL) {
       free(line);
       return NULL;
     }
   }

   return line;
}

Поскольку read может возвращать NULL, вам необходимо изменить

  strcpy(arr[i],read());

, а также почему вы предварительно выделяете строки, а также выделяете в read?в настоящее время вы теряете память, выделяемую каждый раз при чтении

Кажется, лучше заменить цикл на

while((arr[i] == read()) != NULL)
   //printf("%s", arr[i]);  //DEBUG
   i += 1;
}

и удалить предраспределения строк

Другая проблемаэто когда файл содержит более 100 строк (или, может быть, некоторые строки обрезаются слишком долго), в этом случае вы записываете из arr .На самом деле вам не нужно сохранять столько строк, вам просто нужно сохранить максимум 10 строк


Предложение:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *read() {
  char line[80];

  if (fgets(line, 80, stdin) == NULL)
      return NULL;

   return strdup(line);
}

int main()
{
  char * arr[10] = { NULL };
  char * p;
  int i = 0, n = 0;

  while((p = read()) != NULL) {
    n += 1;
    free(arr[i]);
    arr[i] = p;
    if (++i == 10)
      i = 0;
  }

  /* get older line index and line count to print */
  if (n <= 10) 
    i = 0;
  else
    n = 10;

  while (n-- != 0) {
    puts(arr[i]);
    free(arr[i]);
    if (++i == 10)
      i = 0;
  }

   return 0;
}

Compilation and execution :
pi@raspberrypi:/tmp/d $ gcc -g -pedantic -Wextra q.c
pi@raspberrypi:/tmp/d $ ./a.out < q.c
    n = 10;



  while (n-- != 0) {

    puts(arr[i]);

    if (++i == 10)

      i = 0;

  }



   return 0;

}

Примечание. Я не удалил \ nстроки чтения и я использую ставит , поэтому печатаются пустые строки, в то время как строка чтения не обрезается из-за слишком длинной

Если файл короче, чем 10 строк:

pi@raspberrypi:/tmp/d $ tail -n 5 q.c | ./a.out
      i = 0;

  }



   return 0;

}

Под valgrind :

pi@raspberrypi:/tmp/d $ valgrind ./a.out < q.c
==18496== Memcheck, a memory error detector
==18496== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==18496== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==18496== Command: ./a.out
==18496== 


  while (n-- != 0) {

    puts(arr[i]);

    free(arr[i]);

    if (++i == 10)

      i = 0;

  }



   return 0;

}

==18496== 
==18496== HEAP SUMMARY:
==18496==     in use at exit: 0 bytes in 0 blocks
==18496==   total heap usage: 43 allocs, 43 frees, 5,699 bytes allocated
==18496== 
==18496== All heap blocks were freed -- no leaks are possible
==18496== 
==18496== For counts of detected and suppressed errors, rerun with: -v
==18496== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...