Да, внутренний вызов вызывает утечку памяти. Вы можете легко избежать утечки, сохранив возвращаемое значение на месте:
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
даже один раз.