Ошибка SIGSEGV 11 при записи структуры в файл

Пытаюсь записать структуру в файл в бинарном виде, но постоянно выпадает ошибка SIGSEGV 11. не понимаю в чём проблема. Точнее, побочный эффект проявляется, когда записываю строки, в основном. Пытался понять что не так через gdb, но не помогает.

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

#include "student.h"

int read_student(student* st) {
return scanf("%s,%c,%c,%s,%s\n",
st->name, &st->sex, &st->class, st->university, st->job) == 5;
}

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

student* st = malloc(sizeof(student)); student* prev = malloc(sizeof(student));
FILE* out = fopen(argv[1], "wb");

while (read_student(st)) {
    printf("%s -> ", st->name); 
    if (strcmp(st->name, prev->name)) 
        break;

    *prev = *st;
    fwrite(&st, sizeof(st), 1, out);
    printf("success\n");
}

fclose(out);

return 0;
}

Заголовочный файл student.h:

#ifndef __applicant_h__
#define __applicant_h__

typedef struct {
    char name[50]; // фамилия и инициалы
    char sex; // пол
    char class; // буква класса
    char university[50]; // университет 
    char job[30]; // место работы
} student;

#endif

Запускаю в терминале так: (./student.o data.bin) < data.txt

Тестовые данные выглядят так (data.txt):
Artyom A.C.,m,A,Moscow Aviation Institute,Mobile TeleSystem
Maria S.K.,f,B,Moscow State University,Unemployed

Что я делаю не так?


Ответы (1 шт):

Автор решения: Harry

Много, слишком много несуразиц.

Ну, пусть вы не забыли передать имя файла и таки открыли его (вы не проверяете, ни передано ли его имя, ни открылся ли он).

Но дальше при чтении с помощью %s вы читаете одно слово, за которым нет запятой, и благополучно выходите из цикла - scanf возвращает не 5, а 1. Кстати, кто мешал вам вывести хотя бы отладочную запись и посмотреть, что же происходит на самом деле?

Дальше - когда вы исправите, например, как scanf("%[^,],%c,%c,%[^,],%[^\n]", вы пытаетесь использовать неинициализированную память prev. Не то чтоб в данном случае это было сильно страшно, но очень нехорошо. Особенно в других случаях, где это важно.

Вы сравниваете strcmp(st->name, prev->name), а поскольку там мусор (в prev->name), можно спорить, что строки не равны, а значит, функция strcmp вернет не ноль, и вы вылетаете из цикла...

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

По-моему, вы хотели

fwrite(st, sizeof(student), 1, out);

[Грустно] Скажите после этого - а что вы делаете "так"?... И, кстати, нигде ни одну ошибку не проверяете (ну, попытались только со scanf)...

→ Ссылка