#c
Вопрос:
Я пишу функцию, которая помогает мне читать базу данных книг из двоичного файла. Однако при использовании fread у меня возникает ошибка сегментации.
Это та функция, о которой я говорю.
Array *readdb (FILE *db, Array *ind) { Array *database = NULL; Book *book = NULL; indexbook *indentry; char *buffer, bytesdepillar = 0, titprintby[MAX_ENTRADA]; int reader = 0; if (db == NULL || ind == NULL) return NULL; database = malloc(sizeof(Array)); initArray(database, INIT_ARR_SIZE); fseek(db, 0L, SEEK_END); bytesdepillar = ftell(db)/sizeof(char); fseek(db, 0, SEEK_SET); buffer = malloc(bytesdepillar * sizeof(char)); fread(buffer, sizeof(char), bytesdepillar, db); for (size_t i = 0; i lt; ind-gt;used; i ) { book = malloc(sizeof(Book)); indentry = (indexbook*) ind-gt;array[i]; reader = indentry-gt;offset; book-gt;bookID = indentry-gt;key; reader =sizeof(int); memcpy(book-gt;ISBN, amp;buffer[reader], ISBN_LEN); reader =ISBN_LEN; memcpy(titprintby, amp;buffer[reader], indentry-gt;offset indentry-gt;size - reader); strcpy(book-gt;title, strtok(titprintby, "|")); strcpy(book-gt;printedBy, strtok(NULL, "|")); insertArray(database, book); } return database; }
ind-это индекс базы данных со следующей структурой:
typedef struct { int key; long int offset; size_t size; } indexbook;
Файл открывается с помощью
if ((dbf = fopen(db_name, "rb")) == NULL) { fclose(indf); printf("%s does not exist", db_name); return 1; }
Комментарии:
1. Не имеет отношения к вашей проблеме, но
sizeof(char)
(или любой другой тип, основанный наchar
) указан как всегда1
. Вам никогда не нужно умножать или делить на это.2. Что касается вашей проблемы, вы пытались использовать отладчик , чтобы поймать сбой? Когда и где в вашем коде это происходит? Каковы значения всех задействованных переменных в момент и в месте аварии?
3.
chmod -r $db_name; ./a.out $dm_name
приводит к замечательному сообщению об ошибке «$db_name не существует». Файл действительно выходит, но у пользователя нет разрешения на его чтение. Никакое сообщение об ошибке вообще не лучше, чем неправильное сообщение об ошибке.man perror
4.
indentry
не инициализируется.5. @Someprogrammerdude Я использовал gdb, чтобы проверить, где происходит ошибка сегментации. Это происходит в следующей строке:
fread(buffer, sizeof(char), bytesdepillar, db);
Ответ №1:
Как вы уже заявили в разделе комментариев, когда строка
fread(buffer, sizeof(char), bytesdepillar, db);
выполняется, переменная bytesdepillar
имеет отрицательное значение.
Поскольку вы объявили переменную типа char
, в зависимости от вашей платформы, она, вероятно, может представлять значения только между -128
и 127
. Если вызов to ftell
возвращает значение , превышающее 127
значение, оно, вероятно (что именно происходит, определяется реализацией), будет преобразовано в значение между -128
и 127
. Это, скорее всего, причина, по которой это отрицательное значение.
Поэтому я рекомендую вам изменить объявленный тип bytesdepillar
с char
на long
, который является типом , возвращаемым функцией ftell
.
Если после изменения объявленного типа на long
значение продолжает оставаться отрицательным, то это , вероятно, связано с ftell
возвращением функции -1
из-за сбоя функции. В этом случае вы должны убедиться, что db
это относится к допустимому потоку (например, убедитесь, что файл был успешно открыт).
Комментарии:
1. Верно, я не заметил, что объявил это как символ, большое спасибо