2015-07-07 3 views
0

Я новичок в C, так что это может быть глупый вопрос, чтобы спросить:ошибки сегментации с помощью таНос

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

Ниже мой код

common.h

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

typedef struct book * Book; 

struct book{ 
    int id; 
    char *name; 
}; 

extern int b_insert(Book *b, int id, char *name); 
extern int b_print(Book books[], int len); 

insert.c

#include "common.h" 

int b_insert(Book *b, int id, char *name){ 
    Book p; 
    p = (Book)malloc(sizeof(struct book)); 
    p->id = id; 
    strcpy(p->name, name); 

    *b = p; 
    printf("success insert book:\n"); 
    printf("\tID: %d Name: %s\n", (*b)->id, (*b)->name); 

    return 0; 

} 


int b_print(Book books[], int len){ 
    int i; 
    printf("Book List\n"); 
    for(i=0; i<len; i++){ 
     printf("books[%d] = ID: %d, Name: %s\n", i, books[i]->id, books[i]->name); 
    } 
    return 0; 

} 

main.c

#include "common.h" 
#define MAX 2 

int main(){ 
    Book books[MAX]; 
    Book *b=books; 
    int i; 
    int id; 
    char name[10]; 




    for(i=0; i<MAX; i++){ 
     printf("please input new books info\n"); 
     printf("ID: "); 
     scanf("%d", &id); 
     printf("Name: "); 
     scanf("%s", name); 
     if(b_insert(b, id, name) == -1){ 
      printf("fail to insert\n"); 
     } 
     b++; 
    } 

    b_print(books, MAX); 

    return 0; 
} 
+0

Уверена, что ошибка произошла на malloc? использование [assert] (https://en.wikipedia.org/wiki/Assert.h) или [gdb] (http://www.gnu.org/software/gdb/) поможет вам определить проблему – dvhh

ответ

3

Главная проблема:

Выделяем память для p->name перед использованием

strcpy(p->name, name); 

использованием malloc:

p->name = malloc(10); //Or some other size 

Другие проблемы:

  1. Удалить бросание здесь:

    p = (Book)malloc(sizeof(struct book)); 
    

    Почему? Here is the answer

  2. if(b_insert(b, id, name) == -1){ никогда не будет правдой.
  3. Проверьте результат malloc, чтобы проверить, удалось ли выделить выделение памяти.
  4. Проверьте возвращаемое значение всех scanf s, чтобы узнать, удалось ли выполнить сканирование данных.
  5. Добавьте модификатор длины ко второму scanf для предотвращения переполнения буфера:

    scanf("%9s", name); /* +1 for the NUL-terminator */ 
    
+0

Спасибо ! очень подробный ответ! Я боролся с этой проблемой в течение дня ... – user5088802

+0

Кроме того, 'Book p; p = (Книга) malloc' должен быть 'Book * p; p = malloc'. Это одна из нескольких причин, вызывающих сегрегации. – Lundin

+1

@ Lundin этого не делает: 'Book' является typedef, скрывающим указатель. Спасибо за демонстрацию, почему это ужасная идея :) – Quentin

3

Вы не выделяющий место для имени:

int b_insert(Book *b, int id, char *name){ 
    Book p; 
    p = malloc(sizeof(struct book)); 
    if (p != NULL) 
    { 
     p->name = malloc(strlen(name)+1); // It allocates space where the input name will be copied. 

     if (p->name != NULL) 
     { 
      p->id = id; 
      strcpy(p->name, name); 

      *b = p; 
      printf("success insert book:\n"); 
      printf("\tID: %d Name: %s\n", (*b)->id, (*b)->name); 
     } 
     else return -1; // No space to allocate string 
    } 
    else return -1; // No space to allocate struct 

    return 0; 
} 
0

Как упоминалось ранее, выделить место для p->name. Вероятно, вы также должны использовать что-то другое, чтобы прочитать название книги, либо scanf format% ms с указателем на указатель char, либо %9s с вашим буфером, иначе заголовок «война или мир» также приведет к segfault.

+0

'% 10s' не экономит место для NUL-терминатора. –

+0

это правильно. отредактировал мой ответ соответственно. – Gunnar

-1

Здесь вы создаете статическую переменную, и пространство для нее выделяется автоматически.

Book p;

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

p = (Книга) malloc (sizeof (struct book));

Что еще, если вы хотите обратиться к атрибуту статической переменной, вы должны использовать «.». вместо "->". Таким образом, у вас есть два варианта. Создайте указатель и выделите пространство для структуры, а затем «->» oraz создайте статическую переменную.

p-> id = id;

+0

Посмотрите, какой тип 'Книга'. –

Смежные вопросы