Возможна ли в этой функции утечка памяти из-за отсутствия вызова free() при наличии вызова malloc()?

char * concat(const char * first, const char * second)
{
    char * restrict result = NULL;
    size_t first_length = strlen(first);
    size_t second_length = strlen(second);
    result = malloc(sizeof(char) * (first_length + second_length + 1));

    if (result == NULL)
    {
        perror("Error: memory allocation failed.");
    
        exit(EXIT_FAILURE);
    }

    memcpy(result, first, first_length);
    memcpy(result + first_length, second, second_length + 1);

    return result;  
}

Функция предназначена для объединения двух строк за наименьшее время. Компилирую в режиме GCC --std=c2x.


Ответы (2 шт):

Автор решения: Stanislav Volodarskiy

1.

Наличие сбалансированной пары malloc/free не гарантирует вас от утечек памяти:

#include <setjmp.h>
#include <stdlib.h>

jmp_buf buf;

void g() {
    longjmp(buf, 1);
}

void f() {
    char *p = malloc(42);
    g();
    free(p);
}

int main() {
    if (!setjmp(buf)) {
        f();
    }
}
$ gcc -g leak.c 

$ valgrind ./a.out 2>&1 | grep lost
==273705==    definitely lost: 42 bytes in 1 blocks
==273705==    indirectly lost: 0 bytes in 0 blocks
==273705==      possibly lost: 0 bytes in 0 blocks

2.

Отсутствие баланса в функции не означает что будет утечка:

#include <stdlib.h>

char *f() {
    return malloc(42);
}

int main() {
    char *buf = f();

    /* тут используем буфер по назначению */

    free(buf);
}
$ gcc -g ok.c 

$ valgrind ./a.out 2>&1 | grep lost

3.

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

→ Ссылка
Автор решения: evo

Коротко и ясно: нет.

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

P.s, я не понял смысла делать какие-то выводы от setjmp, longjmp, единственное что посоветовал бы, так это убрать выход из программы при ошибке выделения памяти. Это не забота данной функции. Верните пустой указатель, а вызывающая сторона пусть делает то что ей нужно.

→ Ссылка