C Разыменовывающий указатель - PullRequest
0 голосов
/ 19 декабря 2018

Я начал изучать C, и я не знаю, почему приложение продолжает падать.

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

typedef struct
{
    char name[50];
    int age;
}person;

void initPerson(person *aPerson, char name[50], int age)
{
    strcpy(aPerson->name, name); // <- causes a crash
    aPerson->age = age; // <- causes a crash
    printf("%s", aPerson->name);
}

int main()
{
    person *myPerson;
    initPerson(myPerson, "Oscar", 45);

    printf("%s, %i", myPerson->name, myPerson->age);
    return 0;
}

Я отметил линии, которые вызывают сбой.Может кто-нибудь сказать мне, в чем проблема?

1 Ответ

0 голосов
/ 19 декабря 2018

"... приложение продолжает падать., ... Может кто-нибудь сказать мне, в чем проблема?"
Да, ваша программа пытается записать в область памяти, которой она не принадлежит,

Если вы должны использовать указатель на person, создайте немного памяти перед его использованием:

int main()
{
    person *myPerson = calloc(1, sizeof(*myPerson));
    if(!myPerson) return 0; //test if failed

    initPerson(myPerson, "Oscar", 45);

    printf("%s, %i", myPerson->name, myPerson->age);
    free(myPerson);//free memory
    return 0;
}

Или вы можете просто передать адрес не-показатель экземпляра person (с использованием &) для получения тех же результатов:

int main()
{
    person myPerson = {0};

    initPerson(&myPerson, "Oscar", 45);
    printf("%s, %i", myPerson.name, myPerson.age);
    return 0;
}

Оператор:

person *myPerson;

Создает только неинициализированный указатель, не указывающий на какой-либоособое место в памяти во время создания.На этом этапе используется только пробел для самого указателя, sizeof(person *).(4 или 8 байтов для 32-битной или 64-битной цели соответственно.) Прежде чем переменная-указатель может быть использована таким образом, пространство должно быть динамически , выделенным путем вызова _ void * calloc (size_t)nitems, size_t size) _ или семейство.Память, созданная таким образом, устанавливает адрес указателя на ячейку памяти, совпадающую с первым байтом непрерывного блока из nitems*size байтов, выделенных и выделенных для использования с, в данном случае, myPerson.Память, выделенная таким образом, называется кучей памяти и должна быть явно освобождена с помощью вызова free () , когда она больше не нужна.Как правило, этот метод рекомендуется только в том случае, если требования к памяти для конкретной переменной не известны во время компиляции

Но утверждение:

person myPerson;

Статически (Или автоматически , в зависимости от того, когда и где он создан.) выделяет память с sizeof(person) байтами для немедленно используемого экземпляра myPerson, расположенного в памяти по адресу: &myPerson.Память, созданная таким образом, упоминается как стековая память .Поскольку передача адреса myPerson (&myPerson) в качестве аргумента initPerson() и выполнение того же действия, что и с динамически распределенной памятью (обсуждаемой выше), это гораздо более простой вариант, поскольку он не требует каких-либосоздание или освобождение памяти.

Объяснена память стека и кучи.

Обсуждение автоматического, статического и динамического выделения памяти

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...