Внимательно прочитайте документацию scanf
, malloc
, realloc
, поэтому прочитайте их несколько раз.Вы также можете сослаться на стандарт C11 n1570 , в котором они упоминаются (в §7.22.3 ).
Является ли это правильной реализацией realloc ()?
Вы не внедряете realloc
.Вот его шутка-реализация (см. Также это шутка-реализация malloc
):
void *realloc(void*ptr, size_t siz) {
errno = ENOMEM;
return NULL;
}
Конечно, вы бы на самом деле использовали серьезный реализация realloc
(не шутка выше), и она обеспечивается вашей стандартной библиотекой C реализация (например, выше операционная система примитивы или системные вызовы как mmap (2) в Linux).
Итак, нет, у вас нет реализации из realloc
(и вы бы использовали realloc
уже реализовано в вашей стандартной библиотеке C).И (по крайней мере в Linux) вы можете изучить реализацию realloc
, потому что она обычно реализуется внутри некоторого свободного программного обеспечения (например, musl-libc или GNU glibc ). Здесь (в своем файле src/malloc/malloc.c
строка 369) является musl-libc
реализацией realloc
.
вы ошибочно используете realloc
Затем вы используете scanf
как scanf("%s", input)
.Но scanf
возвращает EOF
при ошибке и количество успешно введенных значений при успехе.Обычно EOF
равно -1.Таким образом, в вашем случае, scanf("%s", input)
может вернуть -1 (при ошибке), 0 (если входное значение не было обработано) или 1 (если что-то поместило в input
).
The size_t
- это некоторый беззнаковый целочисленный тип.В моей системе Linux / x86-64 это 64-разрядное число без знака, такое же как unsigned long
.Таким образом, (size_t)(-1)
становится огромным числом, то есть 2 64 - 1. Тогда realloc
обязательно потерпит неудачу (потому что моя система не имеет такого большого количества памяти), если учесть это (size_t)(-1)
поэтому realloc(input, (size_t)-1)
должно дать NULL
.
Если realloc
задано (size_t)0
, это задокументировано в Linux (см. realloc (3) ), чтобы сделать то, что free
делает: освободить заданную память.Но стандарт C не требует такого поведения.
Если задано realloc
(size_t)1
, если будет (или, по крайней мере, разрешено) уменьшить зона памяти (только дляудерживайте один байт, что недостаточно для ваших нужд).
Итак, ваша программа полностью неверна
Кстати, вам нужно обработать ошибку realloc
, поэтомукодирование input = realloc(input, newsize);
очень наивно.
Кроме того, ваш scanf("%6s", input);
неверен (потенциальный переполнение буфера , для ввода ровно шести байтов), так как вам нужно место для завершения NUL символ.
Итак, выбросьте вашу программу в мусорное ведро. Отдохните (или немного повеселитесь).Прочитайте документацию стандартных функций (и вики-страницу C динамического выделения памяти ).Подумай немного.И полностью переписать вашу программу.
Затем скомпилировать вашу программу со всеми предупреждениями и отладочной информацией: gcc -Wall -Wextra -g
с GCC .Улучшите свой код, чтобы не получать предупреждений.Убедитесь, что ваша программа обрабатывает случаи сбоев (scanf
, malloc
, realloc
и т. Д.).Прочитайте Как отлаживать небольшие программы .Используйте отладчик gdb
и valgrind .Будьте напуганы из неопределенное поведение .
Для вашей программы (той, которую вы переписываете с нуля), вас может заинтересовать использование fgets (или даже в Linux getline (3) или readline (3) ...) для ввода.Иногда может потребоваться очистить входной буфер с помощью memset перед выполнением фактического ввода.
Имейте в виду, что stdio буферизуется, а stdout
обычно является строковымбуферизация.Поэтому возьмите в привычку заканчивать строку формата printf
с помощью \n
или используйте fflush
соответствующим образом.
PS.valgrind
доступен в Linux (но не в Windows), и это одна из многих причин, по которой Linux становится очень удобной для разработчиков и студентов системой.Поэтому я рекомендую использовать дистрибутив Linux для изучения программирования на C.