Получение (ядро сброшено) при использовании realloc

void replace(char *str) {
    unsigned int len = 0;
    unsigned int no_of_spaces = 0;
    while (*str) {
        if ((char)*str == SPACE)
            no_of_spaces++;
        str++;
        len++;
    }

    unsigned int new_len = len + 2 * no_of_spaces;
    str = (char*) realloc(str, new_len * sizeof(char));
    str[new_len] = '\0';
}

Я использую функцию как replace("random string");,

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

Для изменения размера я использую realloc но когда я запускаю его, это дает Aborted (core dumped)?

4 ответа

Была ли ваша исходная строка выделена с помощью malloc? или реаллок? Возможно, вы пытаетесь увеличить размер статической строки (строкового литерала):

char sStatic[256];   // cannot realloc

char *sNonStatic = NULL;   // can / must realloc

replace("random string") // cannot realloc within replace

РЕДАКТИРОВАТЬ: после прочтения вашего комментария, вы должны взять копию входящей строки, увеличить размер, а затем вывести копию / новую строку. Вы не можете увеличить размер постоянной строки (строковый литерал).

Единственные указатели, которые можно передать realloc нулевые указатели и те, которые были возвращены calloc , malloc или же realloc ранее!

Это важно, потому что вы упомянули, что вы назвали свою функцию как replace("random string")... Является "random string" нулевой указатель или возвращенный одним из этих *alloc функции? Нет. Возможно, вы хотели использовать strdup или что-то (например, char *foo = strdup("random string"); replace(foo); free(foo);)? strdup является функцией POSIX (например, не C-стандарт, как *alloc функции), но он должен вернуть что-то, возвращенное *alloc функции.


После этого кода:

unsigned int new_len = len + 2 * no_of_spaces;
str = (char*) realloc(str, new_len * sizeof(char)); /* NOTE there's a potential memory leak
                                                     * when realloc returns NULL here, though
                                                     * that's the least of your problems */

... вы должны проверить str для обеспечения realloc удалось, и только тогда единственные действительные индексы для str между 0 и new_len - 1, Это может быть разыменование нулевого указателя или переполнение буфера:

str[new_len] = '\0';

Возможно, вы имели в виду следующее:

size_t new_len = len + 2 * no_of_spaces;
void *temp = realloc(str, new_len + 1); /* <--- NOTE +1 HERE! */
if (temp == NULL) {
    /* XXX: Bomb out due to allocation failure */
}
str = temp;

... и теперь допустимые индексы находятся в диапазоне от 0 до new_len + 1 - 1, так что это действительно:

str[new_len] = '\0';

Эта строка неверна, так как действительные индексы варьируются от 0.. new_len - 1:

str[new_len] = '\0';

Вероятно, должно быть:

str[new_len - 1] = '\0';

У вас также есть несколько других потенциальных проблем:

  • realloc может вернуть NULL - вы должны проверить это

  • в случае сбоя realloc вы теряете оригинал str указатель и получите утечку памяти - вы должны использовать временный указатель для результата, проверить это на NULL, и только в случае успешного выполнения realloc следует установить str равным temp:


char * temp = realloc(str, new_len);
if (temp == NULL)
{
    // handle error here...
}
else
{
    str = temp; // success...
    str[new_len - 1] = '\0';
}

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

Вы также перемещаете указатель

while (*str) {
    if ((char)*str == SPACE)
        no_of_spaces++;
    str++;
    len++;
}

и когда вы в конце, вы пытаетесь перераспределить его. Но вы уже далеко от того, где находится массив. Используйте временную переменную здесь. И, как сказали другие. Надеемся, что строка создается с помощью malloc, а не как массив.

А также str[new_len] = '\0'; вне границ.

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