Получение (ядро сброшено) при использовании 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';
вне границ.