Как перераспределить память, выделенную с помощью calloc? - PullRequest
0 голосов
/ 01 июля 2019

Я выделил строку с помощью функции calloc :

//string1 and string2 previously declared
char *stringClone = calloc(strlen(string1) + 1, sizeof(char));

Теперь я хочу сделать то же самое для stringClone с другой строкой.Делать:

stringClone = calloc(strlen(string2) + 1, sizeof(char));

У меня будет небольшая утечка памяти, верно?Как мне использовать realloc в этом случае?

Ответы [ 2 ]

4 голосов
/ 01 июля 2019

Вы можете использовать realloc() для перераспределения памяти, выделенной malloc(), calloc(), realloc(), aligned_alloc() или strdup(). Обратите внимание, что если перераспределенный блок больше, чем исходный блок, возвращаемый calloc(), вновь выделенная часть будет , а не , инициализироваться для всех нулевых бит.

Обратите внимание, что синтаксис для realloc() не тот, который вы используете: вы должны передать указатель в качестве первого аргумента и один size_t для нового размера. Кроме того, если новый блок не может быть выделен, возвращается NULL, а блок не освобождается, поэтому вы не должны сохранять возвращаемое значение непосредственно в stringClone.

Если вы хотите использовать realloc(), вот что вы должны сделать:

//string1 and string2 previously declared
char *stringClone = calloc(strlen(string1) + 1, 1);
...
char *newp = realloc(stringClone, strlen(string2) + 1);
if (newp == NULL) {
    // deal with out of memory condition
    free(stringClone);
}

Поскольку вам, кажется, не важно, чтобы содержимое stringClone было сохранено в перераспределенном блоке, вам, вероятно, следует просто написать:

//string1 and string2 previously declared
char *stringClone = calloc(strlen(string1) + 1, 1);
if (stringClone == NULL) {
    // deal with out of memory condition
    ...
}
strcpy(stringClone, string1);
...
free(stringClone);
stringClone = calloc(strlen(string2) + 1, 1);
if (stringClone == NULL) {
    // deal with out of memory condition
    ...
}
strcpy(stringClone, string2);

Также обратите внимание, что в POSIX-совместимых системах есть функция выделения памяти, которая очень полезна для вашего случая использования: strdup(s) принимает указатель на строку C, выделяет strlen(s) + 1 байтов, копирует строку в выделенный блок и возвращает его:

//string1 and string2 previously declared
char *stringClone = strdup(string1);
if (stringClone == NULL) {
    // deal with out of memory condition
    ...
}
...
free(stringClone);
stringClone = strdup(string2);
if (stringClone == NULL) {
    // deal with out of memory condition
    ...
}

Обратите также внимание, что приведение к возвращаемому значению malloc, calloc и realloc не является необходимым в C и считается плохим стилем.

0 голосов
/ 01 июля 2019

Причина использования realloc заключается в том, что он сохраняет исходные данные без изменений.Однако, если я правильно понимаю ваш вариант использования, вы намереваетесь стереть исходные данные.В этом случае проще и понятнее просто написать:

char *stringClone = calloc(strlen(string1) + 1, sizeof(char));
// check for calloc error
// use stringClone for string1
free(stringClone);
stringClone = calloc(strlen(string2) + 1, sizeof(char));
// check for calloc error
// use stringClone for string2

Проверка ошибок проще для calloc, чем для realloc, так как временная переменная не требуется.Кроме того, этот шаблон проясняет, что содержимое массива для string1 и string2 не связано.

...