Проанализируйте следующий фрагмент на C и укажите все возможные неопределённые поведения и способы их исправления:
char *f() { char s[10]; strcpy(s, "hello world"); return s; }

18 Ноя в 17:18
2 +1
0
Ответы
1
Основные неопределённые поведения в данном фрагменте и способы их исправления.
1) Переполнение буфера (out-of-bounds write).
Строка `"hello world"` имеет длину 11\,1111\, символов; с завершающим нулём нужно 11+1=12\,11+1=1211+1=12\, байт, а массив объявлен как `s[10]` (101010). Поэтому `strcpy` запишет за пределы `s` — UB. Исправления:
- Выделить достаточно места: `char s[12]; strcpy(s, "hello world");`
- Или безопасно копировать с ограничением длины: `snprintf(s, sizeof s, "%s", "hello world");` (при этом `sizeof s` должно быть не меньше 12\,1212)
- Или использовать динамическую аллокацию (см. ниже).
2) Возврат адреса локального автоматического массива (dangling pointer).
Переменная `s` живёт только в теле функции; возврат указателя на неё приводит к использованию освобождённой памяти — UB. Исправления:
- Вернуть литерал строки: `const char *f(void) { return "hello world"; }` — память статична. Имейте в виду, модифицировать возвращённую строку нельзя.
- Сделать массив статическим: `static char s[12]; strcpy(s, "hello world"); return s;` — работает, но состояние глобальное/общие данные, не потокобезопасно при многократных вызовах.
- Выделить память под результат и вернуть её; обязать вызывающего `free`-ить:
`char *f(void) { char *s = malloc(12); if (!s) return NULL; strcpy(s, "hello world"); return s; }`
или короче: `char *s = strdup("hello world");`
- Сделать интерфейс, где вызывающий предоставляет буфер:
`void f(char *out, size_t n) { if (n>0) snprintf(out, n, "hello world"); }`
Дополнительные рекомендации:
- Всегда проверяйте размеры при копировании строк и используйте `snprintf`, `strncpy`/`strlcpy` (где доступно) или явное выделение памяти.
- Если возвращаете динамически выделённую память — документируйте, кто отвечает за `free`.
- Если возвращаете литерал — используйте `const char *` в сигнатуре, чтобы избежать попыток модификации.
Краткое исправление (рекомендуемое, возвращает выделённую строку):
`char *f(void) { char *s = strdup("hello world"); return s; }` (не забыть `free` в вызывающем).
18 Ноя в 17:24
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир