Понимание моделей владения памятью в C - PullRequest
3 голосов
/ 03 февраля 2020

Я читал о моделях владения памятью в C и наткнулся на следующий пример для объяснения моделей владения памятью в C.

 void Z(void) {
    void *buffer;

    while (!is_queue_empty(&queue)) {
        buffer = queue_pop(&queue);
        // do something useful
        free(buffer);
    }
}

void Y(void **buffer_p, int function) {
    switch (function) {
        // lots of cases
        default:
            enqueue(&queue, *buffer_p);
            *buffer_p = NULL; // "claim ownership"
            break;
    }

}

void X(void) {
    void *buffer = malloc(1024 * 1024);

    Y(&buffer, 3);
}

Может кто-нибудь объяснить, что это значит, когда функция Y "заявляет право собственности", как показано выше? Как это требует собственности? Кроме того, что означает установить *buffer_p = NULL внутри Y, а затем снова вызвать free внутри Z?

Ответы [ 2 ]

8 голосов
/ 03 февраля 2020

В этом примере «владение» означает, кто отвечает за освобождение выделенной памяти. Когда память динамически выделяется с помощью malloc, адрес этой памяти должен быть передан free ровно один раз.

Обратите внимание, что X передает адрес от buffer до Y, что позволяет Y изменить значение этой переменной. Внутри Y он копирует выделенный указатель в структуру памяти очереди. На этом этапе и эта структура, и переменная buffer в X содержат указатель на эту память.

Если бы это было все, что произошло в Y, тогда возник бы вопрос о том, где эта память должна быть освобождена. Следующая строка позаботится об этом, назначив NULL параметру разыменования. Это устанавливает buffer в X на NULL, поэтому теперь X не нужно беспокоиться об этой памяти. Другими словами, владение этой памятью было передано из X в структуру данных очереди.

Если вы посмотрите на Z, вы увидите, что она вытягивает объект из очереди и вызывает free в этой памяти.

1 голос
/ 03 февраля 2020

Стандарт C не предусматривает какой-либо модели владения памятью, кроме того, что если вы выделяете память с помощью malloc (или связанных подпрограмм), память «принадлежит» (зарезервировано для) программе C, которая Выделил его.

Вы можете разрабатывать дополнительные модели собственности. В показанном коде подпрограмма X выделяет память с помощью malloc, а затем «отдает» память подпрограмме Y. Y записывает адрес памяти в очередь, которую она поддерживает. Если мы рассмотрим Y как часть набора подпрограмм, которые управляют вещами в этой очереди (с Y для добавления вещей, Z для удаления вещей и, возможно, других подпрограмм), мы можем создать модель, в которой когда-то память дается этому набору подпрограмм, эти подпрограммы «владеют» памятью и отвечают за то, чтобы в конечном итоге освободить память или передать владение некоторым другим подпрограммам.

Y явно обозначает свое владение, устанавливая указатель, который X передано ему на NULL, в заявлении *buffer_p = NULL;. Это не является обязательным для передачи права собственности - собственность является концептуальной вещью, которую можно передать простым пониманием (возможно, посредством хорошей документации). Некоторые люди предпочитают устанавливать указатели на NULL, когда они больше не должны использоваться, потому что это рассматривается как средство предотвращения ошибок, когда указатель непреднамеренно используется, когда его не следует.

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