Может кто-нибудь объяснить, почему я получаю ошибку сегментации 11? - PullRequest
0 голосов
/ 14 февраля 2019

Вот мой код:

int main() {

    typedef struct {

        int recordCount;
        char *firstName;
        char *secondName;
        char *id;
        char *email;

    }student;

    student *students = malloc(sizeof(*students));

    int i = 0;

    while (students[i].firstName[0] != '.'){

        students[i].firstName = (char *)malloc(sizeof(char*));
        scanf("%s", students[i].firstName);
        i++;
        students = realloc(students, sizeof(students) * (i + 1));

    }
}

Когда я запускаю его через цикл for, он работает, я уверен, что с моим циклом while это просто глупо.

Ответы [ 4 ]

0 голосов
/ 14 февраля 2019

В вашем коде много проблем.

  1. Когда вы используете malloc, вы на самом деле указываете data type, а не pointer type, что, как я считаю, не является вашим намерениемВот.Если вы указываете тип указателя с помощью sizeof, указатель будет указывать на область памяти, имеющую размер указателя.Это не то, что вы хотите в этом случае.
  2. После строки student *students = malloc ....students будет указывать на область памяти, которая будет содержать нулевые значения в firstName.Вам нужно использовать malloc для них.Поскольку вы этого не делаете, вы получаете ошибку сегментации, потому что вы разыменовываете неверный указатель (указывающий на местоположение 0).Вы сначала пытаетесь получить к нему доступ, а затем используете malloc.
0 голосов
/ 14 февраля 2019

Если вы

student *students = malloc(sizeof(*students));

, вы выделяете размер одного указателя.Вместо этого вам нужно вместо

student *students = malloc(sizeof(students));

и по той же причине students[i].firstName = (char *)malloc(sizeof(char*)) совершенно не хватает памяти для вашего имени, попробуйте malloc(sizeof(char)*100) или около того.

0 голосов
/ 14 февраля 2019

malloc возвращает блок неинициализированной памяти.Итак, students[i].firstName - это неинициализированный указатель, который вы пытаетесь разыменовать.Чтение и разыменование неинициализированного указателя вызывает неопределенное поведение, которое в этом случае проявляется как сбой.

Когда вы делаете выделяете место для элемента firstName, вы выделяете только sizeof(char*) байтдля него размер указателя, а не длина строки, которую вы хотите прочитать.

Создайте буфер для чтения строк, достаточно большой для того, что вам может понадобиться, затем используйте strdupсоздать копию для присвоения соответствующему указателю.

student *students = NULL;
int i = 0;
char str[100];

scanf("%99s", str);
while (str[0] != '.'){
    students = realloc(students, sizeof(*students) * (i+1));
    students[i].firstName = strdup(str);
    i++;

    scanf("%99s", str);
}
0 голосов
/ 14 февраля 2019

Для начала

students[i].firstName = (char *)malloc(sizeof(char*));

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

Хотя есть некоторые имена, подойдет (например, Pax или Bob), подавляющее большинство, вероятно, не подойдет.

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

#define MAX_NAME_LEN 100
students[i].firstName = malloc(MAX_NAME_LEN + 1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...