«ошибка шины» и «Ошибка сегментации» с минимальным кодом, содержащим структуру на C

#c #pointers #segmentation-fault #scanf #bus-error

#c #указатели #сегментация-ошибка #сканф #ошибка шины

Вопрос:

Я написал минимальный код на C следующим образом:

 #include <stdio.h>

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};

int main() {
   struct Books Book1;

   char *tmp;
   int counter=0;

   scanf("%s", tmp);
   return 0;
}
 

Когда я компилирую и запускаю приведенный выше код, после ввода входных данных я получаю следующую ошибку:

 ❯ gcc main.c
❯ ./a.out
e
[1]    86266 bus error  ./a.out
❯ vim main.c
$
 

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

Я понятия не имею, что не так с этим кодом. Это прекрасно работает, когда я комментирую первую строку main (instatioation структуры). Любое объяснение будет оценено по достоинству.

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

1. Измените char *tmp на что-то вроде char tmp[1000] .

Ответ №1:

tmp это указатель, который никуда не указывает. Он неинициализирован, что означает, что его значение не определено. Поэтому, когда вы передаете этот указатель scanf , он пытается разыменовать этот недопустимый указатель. Это вызывает неопределенное поведение, которое в вашем случае приводит к сбою программы.

Измените tmp на массив, достаточно большой, чтобы содержать нужное значение, и обязательно укажите максимальный размер поля в вашем scanf формате:

 char tmp[50];
scanf("Is", tmp);
 

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

1. Но scanf предполагает также работать с char *, верно? Почему код работает, когда я тогда комментирую определение структуры?

2. @компоновщик Это один из способов проявления неопределенного поведения. Казалось бы, несвязанное изменение может привести к сбою вашего кода (или не к сбою).

3. @linker: scanf ожидает, что указатель будет указывать на допустимую выделенную память. Либо путем выделения массива, как показано, либо вы можете выделить в куче : char *tmp = malloc(50); .