Можно ли постоянно малло c без свободной памяти? - PullRequest
2 голосов
/ 28 апреля 2020

Вот мой код:

struct movie {
    char movie_name[30];
    float score;
    struct movie *next;
};

typedef struct movie *p_movie;
void print_all(struct movie *head);

int main() {
    p_movie head = NULL;
    p_movie new_node = malloc(sizeof(struct movie));
    if (new_node == NULL) {
        exit(1);
    }
    strcpy(new_node->movie_name, "Avatar");
    new_node->score = 9.5f;
    new_node->next = NULL;
    if (head == NULL)
        head = new_node;
    print_all(head);
    new_node = malloc(sizeof(struct movie));
    if (new_node == NULL) {
        exit(1);
    }
    strcpy(new_node->movie_name, "Aladdin");
    new_node->score = 8.0f;
    new_node->next = NULL;
    p_movie temp = head;
    head = new_node;
    new_node->next = temp;

    print_all(head);
}

void print_all(struct movie *head) {
    printf("---------------------\n");
    printf("Head address = %zd\n", (size_t)head);
    struct movie* search = head;
    while (search != NULL) {
        printf("%zd \"%s\" %f %zd\n", (size_t)search, search->movie_name,
               search->score, (size_t)search->next);
        search = search->next;
    }
}

Я в замешательстве из-за malloc: он работает хорошо, но я не знаю, почему этот код работает хорошо.

Мой вопрос о new_node: во-первых, я выделяю память для new_node, и я не освобождаю ее и снова выделяю память.

Затем, что происходит с первой памятью (Avatar)? Это удалено? или где-то сохранено ..?

Ответы [ 3 ]

2 голосов
/ 28 апреля 2020

Можно ли постоянно малло c без свободной памяти?

По идее да. На практике только до тех пор, пока у вас не закончится память.

сначала я выделяю память на new_node.

И я не освободил ее и снова выделил память.

тогда, что происходит с первой памятью (Аватар)?

Это удалено? или где-то сохранено ..?

В вашем конкретном примере: если head == NULL, оно (очевидно) сохранено. Здесь «это» относится к указателю на эту память.

Если бы head не было NULL (что невозможно в этом месте), у вас была бы утечка памяти: вы выделили память, которая вы больше не можете ссылаться.

Как правило, после malloc() вы можете хранить эту память столько, сколько вам нужно. Это включает в себя сохранение его до конца вашей программы. Но если вы не сохраните указатель на эту память, вы ничего не сможете с ним сделать: ни использовать, ни освобождать его. В этом случае вашей программе требуется больше памяти, чем нужно, и если это происходит регулярно, это в конечном итоге приведет к ненужному засорению вашей памяти.

Однако в вашем случае вы сохраняете это new_node в head, так что это не потеряно. После этого вы можете использовать new_node (это просто переменная для удержания указателя!) Для других целей.

Я бы предложил перенести выделение нового узла в отдельную функцию:

p_movie alloc_movie(char * name, float score)
{
    p_movie new_node = malloc(sizeof(struct movie));
    if (new_node == NULL) {
        return NULL; // let the caller handle that
    }
    strcpy(new_node->movie_name, name);
    new_node->score = score;
    new_node->next = NULL;
    return new_node;
}

и используйте это с

int main()
{
    p_movie head = NULL;
    p_movie new_node = alloc_movie("Avatar", 9.5f);
    if (new_node == NULL)
    {
        exit(1);
    }
    // if (head == NULL) is unnecessary, as we can be sure it is null
    head = new_node;
    print_all(head);

    new_node = alloc_movie("Aladdin", 8.0f);
    if (new_node == NULL)
    {
        exit(1);
    }

    // Put the new node as the head, let the old head then be the next item.
    p_movie temp = head;
    head = new_node;
    new_node->next = temp;

    print_all(head);
}

или даже короче:

p_movie alloc_movie(char * name, float score, p_movie next)
{
    p_movie new_node = malloc(sizeof(struct movie));
    if (new_node == NULL) {
        return NULL; // let the caller handle that
    }
    strcpy(new_node->movie_name, name);
    new_node->score = score;
    new_node->next = next;
    return new_node;
}

int main()
{
    p_movie new_node = alloc_movie("Avatar", 9.5f, NULL);
    if (new_node == NULL)
    {
        exit(1);
    }
    p_movie head = new_node;
    print_all(head);

    // Create a new node, with the old head as its "next".
    new_node = alloc_movie("Aladdin", 8.0f, head);
    if (new_node == NULL)
    {
        exit(1);
    }

    // Overwrite the head, as its old value is already saved in the "Aladdin" node.
    head = new_node;
    print_all(head);
}
2 голосов
/ 28 апреля 2020

Сначала я выделяю память для new_node. И я не освободил это и снова выделил память. Затем, что происходит с первым воспоминанием (Аватар)? Это удалено? или где-то сохранено ..?

Пока вы не free() d памяти, выделенной предыдущими вызовами функций управления памятью, она будет храниться в памяти до завершения программы.

Могу ли я постоянно malloc память без free?

Это зависит от объема вашей памяти (как долго он способен удерживать постоянно суммирующуюся незанятую память куски и выделить новую память). В определенный момент у вас будет недостаточно памяти, если вы продолжите запасать память и свою программу, и рабочая машина может получить sh.


Тем не менее, это не хорошая практика, чтобы запастись неиспользуемая память, даже если ваша память технически может справиться с этим. Всегда free() больше не нужна динамическая c память.

1 голос
/ 28 апреля 2020

Могу ли я постоянно загружать c память без свободной памяти?

Да, на практике, и многие программы malloc вводят некоторые данные - во время инициализации - не заботясь о free это. Но если вы делаете это слишком часто, у вас огромная утечка памяти .

Нет, в теории. Прочитайте стандарт C11 n1570 .

Не забывайте, что malloc может дать сбой.

Имеет смысл написать программу, которая malloc данных при запуске ; сделать сложные вычисления на нем, и просто exit -s. Большинство (но не все) операционных систем могут справиться с этим, потому что, когда процесс завершается, операционная система kernel (например, Linux) освобождает ресурсы, потребляемые процессом. Прочитайте о виртуальном адресном пространстве и хорошем учебнике о операционных системах .

Но такая практика уродлива и хрупка. При таком кодировании вы не сможете преобразовать свою программу в библиотеку многократного использования. Несколько серьезных программ (включая компилятор G CC, в определенный момент времени) сделали malloc без free -ing до exit -ing или return ing с их main

Вкл. Linux, см. Также pmap (1) , mmap (2) - используется mallo c (3) - и strace (1) и, конечно, valgrind .

Будьте в курсе самых быстрых в мире mallo c. Практически не очень полезно. ? (но соответствует стандарту).

Также следует помнить о чрезмерной памяти .

...