Ошибка сегментации: сброс ядра

#c

#c

Вопрос:

 #include <stdio.h>

int main(){

   FILE *fp = ("Hello.txt","w");
   fprintf (fp, "n Hello World");
   fclose(fp);
   return 0;
}
  

Я получаю это сообщение при запуске этой программы

«Ошибка сегментации (сброс ядра)».

Было бы очень полезно, если бы я получил представление о том, почему это происходит и как это исправить. В настоящее время я использую
кодовые блоки в ubuntu. Заранее спасибо 🙂

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

1. FILE *fp = ("Hello.txt","w"); -> FILE *fp = fopen("Hello.txt","w"); Разве ваш компилятор не показывал хотя бы предупреждения?

2. Перед использованием функции fprintf() вы проверили, был ли файл успешно создан ==> fp != NULL?

3. Да, пропустил это 🙂

4. @J.Piquard, учитывая это состояние его кода, эта проверка действительно пройдет.

Ответ №1:

да. как прокомментировал Майкл Уолц. вы пропустили fopen

 #include <stdio.h>

int main(){

   FILE *fp = fopen("Hello.txt","w");
   fprintf (fp, "n Hello World");
   fclose(fp);
   return 0;
}
  

Ответ №2:

В вашем коде отсутствует fopen. Кроме того, чтобы избежать других проблем, всегда проверяйте возвращаемое значение fopen. Значение будет нулевым, если при открытии файла что-то пошло не так (например, не хватает места, неправильные разрешения)

 #include <stdio.h>

int main(int argc, char **argv)
{

    FILE *fp = fopen("Hello.txt", "w");

    if (fp==NULL)
        return -1;

    fprintf (fp, "n Hello World");
    fclose(fp);

    return 0;
}
  

Ответ №3:

Строка:

 FILE *fp = ("Hello.txt","w");
  

явно ошибочен с точки зрения намерения, поскольку вы, похоже, пропустили этап указания компилятору, какую фактическую функцию вы хотите вызвать. То, что вы почти наверняка хотели сделать, было:

 FILE *fp = fopen("Hello.txt", "w");
  

Любой приличный компилятор должен был предупредить вас об этом, например, с gcc предупреждением:

 FILE *fp = ("Hello.txt","w");
           ^
warning: initialization from incompatible pointer type
  

и я часто компилирую с -Werror флагом, чтобы компилятор обрабатывал предупреждения как ошибки, чтобы перехватывать именно такие вещи.


На самом деле вам может быть интересно, почему компилятор считает это просто предупреждением, но правда в том, что это совершенно корректный код. Круглые скобки вокруг выражения допустимы, поэтому вы можете написать либо x = 7 , либо x = (7) , либо даже x = (((((7))))) , и это будет означать одно и то же.

Тогда остается только выражение, заключенное в круглые скобки, и для этого используется оператор запятой C. По сути, выражение a, b вычисляет a (отбрасывая результат), затем вычисляет b и использует это как результат выражения.

Вы можете проверить это поведение с помощью следующей программы, которая выводит w :

 #include <stdio.h>
int main (void) {
   char *fp = ("Hello.txt", "w");
   puts (fp);
   return 0;
}
  

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

 for (i = 0, j = 0; i < 100; i  , j  = 2)
    printf ("%d x 2 = %dn", i, j);
  

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


В вашем случае утверждение:

 FILE *fp = ("Hello.txt","w");
  

будет оценивать "Hello.txt" и использовать "w" для присвоения fp (отсюда предупреждение о несовместимости указателя).

Затем, когда вы пытаетесь использовать адрес "w" , как если бы это был действительный FILE указатель, все ставки отменяются.


И, в качестве дополнительного примечания, вам обычно следует проверять возвращаемое значение всех функций, которые могут завершиться сбоем, если такой сбой может впоследствии повлиять на вашу программу. Неразумно предполагать, что fopen (или malloc , или множество других функций) будут работать всегда. Для fopen это вопрос обеспечения того, чтобы возвращаемое значение не было NULL .