Кейс (C): объясните, что делает и в чём ошибка в следующем фрагменте — почему поведение неопределённо и как это исправить: char *s = malloc(10); strcpy(s, "this string is way too long"); free(s); strcpy(s, "another");

14 Ноя в 10:32
2 +1
0
Ответы
1
Кратко: в коде две проблемы, обе вызывают неопределённое поведение (UB).
1) Переполнение буфера: выделено 101010 байт, затем копируется строка длиннее этой памяти — это записывает за границы выделенного блока и ломает кучу/данные -> UB (возможны крах, молчалое повреждение памяти, уязвимость).
2) Использование после освобождения (use-after-free): после `free(s)` указатель больше не указывает на валидную память, `strcpy(s, ...)` снова записывает в освобождённый участок -> UB.
Как исправить (варианты):
- Выделять ровно столько памяти, сколько нужно:
char *s = malloc(strlen("this string is way too long") + 1);
if (!s) { /* обработка ошибки */ }
strcpy(s, "this string is way too long");
free(s);
s = malloc(strlen("another") + 1);
strcpy(s, "another");
free(s);
Здесь размеры указаны как strlen("...")+1strlen("...") + 1strlen("...")+1.
- Или использовать `realloc` вместо `free`+нового `malloc`:
char *s = malloc(strlen(...)+1);
/* ... */
s = realloc(s, strlen("another")+1);
strcpy(s, "another");
free(s);
- Или использовать удобные/безопасные функции:
- `strdup("...")` (POSIX) для одновременного выделения и копирования;
- `snprintf` или `strncpy` с явной границей длины (но с осторожностью: `strncpy` не гарантирует завершающий NUL).
- После `free(s)` безопаснее присвоить `s = NULL;`, чтобы лишний `strcpy(s, ...)` сразу давал явные ошибки (или проверять).
Итого: выделяйте достаточный объём памяти (strlen(строка)+1strlen(\text{строка})+1strlen(строка)+1), не записывайте вне границ и не используйте указатель после `free`.
14 Ноя в 10:39
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир