Как освободить символ *, который будет возвращен?

Скажем, у меня есть функция ниже:

char* fakeTrim(char* input) {
    char* temp = malloc(strlen(input));
    int count = 0;
    for(int i = 0; i < strlen(input); i++) {
        if(input[i] != ' ')
            temp[count++] = input[i];
    }
    temp[count] = '\0';
    return temp;
}

Вызывает ли временная утечка утечку памяти? Если так, то возможно ли освободить его до того, как мы вернемся?

Спасибо!

3 ответа

Решение

Нет, конечно, вы не можете освободить память, которая принадлежит данным, которые вы возвращаете. И действительно, выделение памяти в служебной функции, подобной этой, делает утечки памяти чрезвычайно вероятными; так как вызывающая сторона не увидит тело функции, ей будет очень легко забыть освободить его. На самом деле существует стандартное решение этой проблемы, которое заключается в том, чтобы вызывающая сторона выделяла память самостоятельно:

void fakeTrim(const char* input, char* temp) {
    int count = 0;
    for(int i = 0; i < strlen(input); i++) {
        if(input[i] != ' ')
            temp[count++] = input[i];
    }
    temp[count] = '\0';
}

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

Изменить: Вот пример использования:

const char* input = "Hello world";
char* temp = malloc(strlen(input)+1);
fakeTrim(input, temp);
// ... do something with temp
free(temp);

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

Кстати, вы получите ссылку на массив за пределами temp[count] = '\0'; если в вашей входной строке нет пробелов, вы должны выделить еще один байт. (А также trim обычно не удаляет внутренние пробелы, но, возможно, именно поэтому вы назвали это fakeTrim.)

Да, действительно, температура вызовет утечку памяти.

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

void main()
{
        char *test;

        setVal(test);
        puts(test);
        if(test){
                free(test);
                test = NULL;
        }
}
void setVal(char **data)
{
        char retry[100]="This is test";
        char *ret;

        ret = malloc((strlen(retry))*sizeof(char));
        if(ret == NULL)
                exit(1);
        strncpy(ret, retry, strlen(retry));

        *data = ret;
}

Если вы все еще не удовлетворены. Используйте примеры кодов, которые я предоставил с VALGRIND, чтобы увидеть, есть ли утечка памяти.

Надеюсь, поможет.

Другие вопросы по тегам