Дан фрагмент кода на C: char *s = strdup(buf); free(buf); printf("%s", buf); — объясните, какие ошибки управления памятью здесь допущены, какие возможны последствия и как правильно переписать код
Ошибки: - Использование указателя после `free`: `printf("%s", buf);` — use‑after‑free, поведение неопределено (крах, мусор, утечка данных, уязвимость безопасности). - Отсутствует проверка результата `strdup` на `NULL` (OOM). - Возможна утечка памяти, если вы не освободите `s` позже. - Если `buf` указывает не на область, выделенную динамически (строка литерал), то `free(buf)` вообще некорректен. Возможные последствия: программа может аварийно завершиться, напечатать мусор, коррумпировать память, дать атакующему возможность раскрыть/использовать данные. Правильные варианты в зависимости от намерения: 1) Если нужно сделать копию, освободить старую и печатать копию: ```c char *s = strdup(buf); if (s == NULL) { perror("strdup"); /* обработка ошибки */ } free(buf); printf("%s", s); free(s); ``` 2) Если вы хотите передать владение без копирования (убрать `strdup`): ```c char *s = buf; /* передали владение */ printf("%s", s); free(s); ``` 3) Если `buf` может быть строковым литералом — не вызывать `free(buf)`; освобождать только то, что реально выделяли через malloc/strdup. Дополнительно: `free(NULL)` безопасен; никогда не использовать указатель после `free`; всегда проверяйте возвращаемые указатели от функций выделения памяти.
- Использование указателя после `free`: `printf("%s", buf);` — use‑after‑free, поведение неопределено (крах, мусор, утечка данных, уязвимость безопасности).
- Отсутствует проверка результата `strdup` на `NULL` (OOM).
- Возможна утечка памяти, если вы не освободите `s` позже.
- Если `buf` указывает не на область, выделенную динамически (строка литерал), то `free(buf)` вообще некорректен.
Возможные последствия: программа может аварийно завершиться, напечатать мусор, коррумпировать память, дать атакующему возможность раскрыть/использовать данные.
Правильные варианты в зависимости от намерения:
1) Если нужно сделать копию, освободить старую и печатать копию:
```c
char *s = strdup(buf);
if (s == NULL) {
perror("strdup");
/* обработка ошибки */
}
free(buf);
printf("%s", s);
free(s);
```
2) Если вы хотите передать владение без копирования (убрать `strdup`):
```c
char *s = buf; /* передали владение */
printf("%s", s);
free(s);
```
3) Если `buf` может быть строковым литералом — не вызывать `free(buf)`; освобождать только то, что реально выделяли через malloc/strdup.
Дополнительно: `free(NULL)` безопасен; никогда не использовать указатель после `free`; всегда проверяйте возвращаемые указатели от функций выделения памяти.