Обнаружена ошибка сегментации, но перед этим оптимизируется сообщение - PullRequest
0 голосов
/ 05 мая 2018

Я написал следующий код в онлайн-отладчике GDB:

#include <stdio.h>

int main()
{
  printf("jkjkkjkj");

  int p , n;
  FILE *fp;
  printf("jkjkkjkj2");
  fp = fopen("abc.txt","r");

  while ( (n = getc(fp))!= EOF)
  {
    printf( "the chareacter here is %d \n", n);
  }

  n = fclose(fp);
  return 0;
}

При выполнении кода я получаю ошибку сегментации в строке, где я пытаюсь извлечь символы из файла. Я знаю, что поскольку файл не существует, возникает ошибка ошибки сегментации.

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

optimized out written near the line no

Однако я попытался поместить getchar() здесь и там, сообщения выводились на экран, даже если ошибка сегментации сохраняется.

Как это объяснить? Почему это происходит? Почему сообщения печатаются, когда я помещаю getchar() в разные места?

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

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Поскольку ответил Yunnosch , вы, вероятно, забыли проверить на предмет отказа fopen (3) . Лучшая привычка - всегда проверять, по крайней мере, кодируя:

  fp = fopen("abc.txt","r"); 
  if (fp == NULL) { perror("fopen abc.txt"); exit(EXIT_FAILURE); };

и привыкни делать это, по крайней мере, везде. Использование perror (3) (или strerror (3) с errno (3) ) является полезной привычкой, так как вам нужна причина, связанная с неудача (дается errno возможно через perror).

В общем, всегда читайте документацию функций, которые вы используете (для стандартных функций, по крайней мере на некоторых справочных веб-сайтах и, возможно, в стандарте C11 n1570 ) и позаботятся о том, как обработать их ошибку (по крайней мере, путем проверки на отказ и выхода с полезным сообщением stderr); для функций Unix см. их страницы man (в Linux начните с intro (2) и intro (3) ; для Solaris начните с intro (2) & intro (3) ..). В вашем Unix-терминале попробуйте также man fopen ... Для стандарта POSIX запустите здесь .


меня заинтриговало отсутствие сообщений, которые я пытаюсь напечатать на экране.

Это просто. stdout буферизуется (см. Также setvbuf (3) ) и часто буферизуется строкой. Таким образом, printf, который не заканчивается на \n, выводится в буфере, но еще не на экране. Привычка - почти всегда заканчивать строку формата управления printf (3) новой строкой, либо явно очищать буфер, используя fflush (3) .

Для новичка есть несколько причин, чтобы не заканчивать ваш printf явным \n. Так что используйте вместо

printf("jkjkkjkj\n");

В противном случае, вызывайте fflush(NULL); довольно часто в вашей программе. Кстати, по этим причинам буферизации, fflush(NULL) должно быть сделано перед вызовом system (3) , fork (2) , execve (2) и других важные функции всей программы.


оптимизировано написано около строки №

Это, вероятно, происходит в самой стандартной библиотеке C (например, в getc из некоторых libc.so), которая обычно не компилируется с отладочной информацией. На практике доверяйте своей стандартной библиотеке C: в вашем коде гораздо больше ошибок, чем в libc.

Ваш собственный исходный код должен быть скомпилирован с gcc -Wall -Wextra -g (с просьбой к компилятору GCC выдать все предупреждения и отладочную информацию в формате DWARF , который может использоваться gdb отладчик), и вам нужно улучшить свой код, чтобы вообще не получать предупреждений до с помощью отладчика gdb .

Осознайте неопределенное поведение , потратьте несколько часов на чтение UB и будьте напуганы UB.

0 голосов
/ 05 мая 2018

Попробуйте защититься от NULL в fp и для правильной меры убедитесь, что выходные данные отладки напечатаны (как в комментариях Некоторого Программиста Чувак).

#include <stdio.h>

int main(void)
{    
   int p , n;
   FILE *fp;

   printf("jkjkkjkj2\n");
   fp = fopen("abc.txt","r"); 

   if (NULL != fp)
   {
      while ( (n = getc(fp))!= EOF)
      {
           printf( "the chareacter here is %d \n", n);
      }
      n = fclose(fp);
   } else
   { 
       printf("File opening failed somehow!\n");
   }
   return 0;
}

Обратите внимание на приятное прикосновение (от Basile Starynkevitch), чтобы закрыть только то, что было успешно открыто.

...