Сохраняется ли выделенная память в функции после выделения функции?

Для кода ниже: (1) "main" вызывает функцию "f1". (2) функция "f1" выполняет некоторые функции хруста; создает массив "char" с malloc, а затем возвращает указатель массива на главный (без выделения выделения -freeing-array).

У меня есть 3 вопроса, связанные со случаем: (1) Я предполагаю, что хотя функция "f1" завершена, выделенный массив char по-прежнему остается выделенным до тех пор, пока основная программа полностью не завершится. То есть выделенная память по-прежнему принадлежит основному, и никакой другой процесс не может получить доступ (я имею в виду, вмешиваться) его извне. Я прав? (2) Должен ли я освобождать массив (выделенный в "f1" ) до того, как программа завершится (или освободится, как только закончится основная программа)? (3) Если ответ на второй вопрос "да", то как вы освободите массив, выделенный в другой функции?

note: Я хочу оставаться в пределах чистого c и не переливаться на С++.

char *f1 (...) {
    ...
    ...
    char *fTmp = malloc (length1 * sizeof (char));
    char *fData = malloc (length2 * sizeof (char));
    ...
    ...
    free (fTmp);
    return (fData);
}

int main () {
    char *fData = f1 (...);
    ...
    return (0);
}

Ответ 1

Я предполагаю, что хотя функция "f1" завершена, выделенный массив char все еще остается выделенным до тех пор, пока основная программа не завершится полностью.

True. Динамически распределенная память не имеет ничего общего с функциями, она принадлежит процессу.

То есть выделенная память по-прежнему принадлежит основному, и никакой другой процесс не может получить к ней доступ извне. Я прав?

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

Нужно ли мне освобождать массив (выделенный в "f1" ) до того, как программа завершит (или освободится, как только закончится основная программа)?

Да. Нераспределенная память - в большинстве систем - автоматически освобождается операционной системой, когда процесс завершается, но это зависит от системы. IMO, даже когда OS это делает, вы всегда должны освобождать, используя такое автоматическое освобождение как красный флаг (я забыл, что для освобождения, это ошибка, которую я пропустил?). Более того, если f1 вызывается 1000 раз, это будет утечка памяти каждый раз, когда он быстро съедает всю доступную память. Подумайте о процессе на сервере, он может (и должен) работать и работать в течение многих лет.

Если ответ на второй вопрос "да", то как вы освободите массив, выделенный в другой функции?

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

char* pBuffer = f1();
// Use it
free(pBuffer);

Обратите внимание, что существует много методов, если вы хотите скрыть такой внутренний указатель. Вы можете использовать токен (например, целое число, ключ в словаре), typedef или непрозрачный тип.

Ответ 2

  • Да, память, выделенная с помощью malloc(), остается, пока она не будет освобождена. Как еще могла функция когда-либо возвращать данные переменной размера своему вызывающему?

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

  • Вы вызываете free() по указателю, возвращаемому функцией. Таким образом, в вашем случае main() может выполнить free(fData) после выполнения массива.

Все это должно охватываться любым классом программирования C или учебником.

Ответ 3

malloc выделяет память в кучу, и поэтому эта память остается выделенной до тех пор, пока она не будет освобождена функцией free или завершением программы.
В вашем случае вы освободили ftemp в f1, чтобы он больше не существовал после завершения функции. fdata по-прежнему находится в куче, и он доступен main, поскольку вы возвращаете указатель на выделенное место.

Как только main завершается успешно, память, отмеченная fdata, освобождается.

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

Ответ 4

Использование malloc будет выделять память в куче, пока она не будет free.

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

В основном вы должны free(fData) избежать утечки памяти.

Подводя итог:

1) Ваше первое предположение верно, второе и третье - нет. Он останется выделенным, но не локальным по отношению к основному, а не связан с процессом, поскольку он завершает.

2) Да, вы должны освободить его

3) Используйте указатель, который вы получаете от функции. Если вы не вернете указатель на выделенные данные из функции, убедитесь, что функция free it.

Ответ 5

  • Да, это все еще в куче. Однако вы запутываете концепцию процесса. Если вы не создаете другой процесс (используя fork on * nix), он все тот же процесс.

  • Хорошая привычка освобождать память, когда она не используется. Но если программа завершается нормально, выделенная память освобождается системой.

  • Вот так:

    int main () {
        char *fData = f1 (...);
        //...
        free(fData);
        //...
    }
    

Ответ 6

Существует два основных типа памяти, с которыми вы можете работать в C. Этими типами являются стек и куча. В общем, переменные, которые вы создаете внутри функции, будут выделены в стеке и будут освобождены при возврате функции. Память, выделенная в куче, будет сохраняться, и вы обязаны управлять этим распределением внутри своей программы. Память в куче будет оставаться выделенной до тех пор, пока вы не освободитесь, используя указатель (адрес памяти), который ссылается на блок данных.

Маленькое чтение на обоих поможет вам понять. Я хотел бы указать, что у вас есть два экземпляра fData, каждый из которых имеет свою собственную область. Оба указателя указывают на память, которую вы выделяете:

char *fData = malloc (length2 * sizeof (char));

.. даже несмотря на то, что они передаются и выходят за пределы области выполнения вашего кода.

Ответ 7

Если вы не освобождаете память, которую вы не используете, в конце концов это будет накапливаться, если вы сделали это со многими другими указателями, и ваша программа может закончиться без памяти. После освобождения блока памяти с помощью функции free я также предложил бы назначить NULL указателю, поскольку это защищает от оборванных указателей, даже если вы освободили указатель, если вы попытаетесь получить к нему доступ, вы можете получить undefined, тогда как доступ и операции с указателями NULL приводят к сбою, поэтому вы легко сможете отслеживать проблему.