Что происходит с памятью, выделенной при вызове функции, вот так? - PullRequest
1 голос
/ 10 марта 2019

У меня есть вопрос о следующей функции и о распределении памяти.

char    *strjoin(char const *s1, char const *s2)
{
    char    *s3;

    s3 = NULL;
    if (s1 && s2)
    {
        s3 = (char *)malloc(sizeof(char) * (strlen(s1) + strlen(s2) + 1));
        if (!s3)
            return (NULL);
        strcpy(s3, s1);
        strcat(s3, s2);
    }
    return (s3);
}

int main()
{
    char    *s1 = "my favorite animal is";
    char    *s2 = " ";
    char    *s3 = "the nyancat";
    char    *res = strjoin(strjoin(s1, s2), s3);
}

Документ strjoins выглядит следующим образом:

Распределяет (с помощью malloc (3)) и возвращает «свежую» строку, заканчивающуюся на ’\ 0’, результат объединения s1 и s2. Если распределение не работает, функция возвращает NULL.

В основной функции функция вызывает себя в этой строке:

char * res = strjoin (strjoin (s1, s2), s3);

Поскольку память выделяется в strjoin (s1, s2), но никогда не назначается чему-либо, и она используется во внешнем вызове функции, но никогда не освобождается технически, разве эта память просто протекает и остается неиспользованной?

1 Ответ

1 голос
/ 10 марта 2019

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

char    *intermediate;
char    *res = strjoin(intermediate = strjoin(s1, s2), s3);
free(intermediate);

или

char    *intermediate = strjoin(s1, s2);
char    *res = strjoin(intermediate, s3);
free(intermediate);

Но память будет освобождена операционной системой main функция / при вызове exit, если это размещенная система. Если вы не программируете встроенное устройство, драйвер устройства или операционную систему, вы, скорее всего, ориентируетесь на хост-платформу.


Теперь, в зависимости от того, является ли компилятор умным или нет, он может фактически не выделить любую память для этой программы, потому что результат не нужен.

Рассмотрим слегка измененную программу:

#include <stdlib.h>
#include <string.h>

static inline __attribute__((always_inline)) char *strjoin(char const *s1, char const *s2)
{
    char    *s3; 
    s3 = NULL;

    if (s1 && s2) {
        s3 = malloc(strlen(s1) + strlen(s2) + 1);
        strcpy(s3, s1);
        strcat(s3, s2);
    }

    return s3;
}

int main()
{
    char    *s1 = "my favorite animal is";
    char    *s2 = " ";
    char    *s3 = "the nyancat";
    char    *res = strjoin(strjoin(s1, s2), s3);
}

Я добавил static inline __attribute__((always_inline)) в функцию, чтобы она видна только в пределах области видимости , но не из других файлов .c (у нее нет external связь ), и что функция всегда будет встроена на месте; Я также удалил проверку возвращаемого значения для malloc, так как это, похоже, мешает GCC определить, что здесь произойдет. (почему-то кажется, что отслеживание состояния NULL malloc актуально).

Если вы скомпилируете эту программу с наивысшим уровнем оптимизации с помощью последней магистрали GCC , компилятор заметит, что все вычисления бесполезны, и скомпилирует гораздо более простую программу :

int main(void) {
}

(см. Идентичную сборку на средней панели), которая будет иметь такое же наблюдаемое поведение , но которое не вызывает malloc даже один раз.

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