Спасибо за уточнение — теперь картина полностью ясна.
У тебя примерно такая логика:
И вот что происходит при Ctrl+C:
- Программа находится в
fgets(stdin)— ждёт ввода. - Нажимаешь Ctrl+C → приходит SIGINT.
fgets()прерывается и возвращаетNULL.- Цикл завершается.
- Программа идёт дальше → открывает файл в режиме
"w"→ начинает запись. - НО В этот момент приходит сигнал снова или программа аварийно завершается →
fclose()не вызывается → файл повреждается или обнуляется.
🔍 Почему файл становится 0 байт?
Потому что:
- Ты открываешь файл в режиме
"w": - Даже если программа не успела ничего записать, файл уже пустой.
- Если после этого она аварийно завершается (например, из-за повторного
SIGINTилиexit()безfclose), то:- Буфер не сбрасывается,
- ОС может не считать файл корректно закрытым,
- Но файл уже обнулён на этапе
fopen()!
💥 То есть главная проблема — режим
"w"в сочетании с прерыванием после открытия, но до записи.
✅ Как исправить?
✅ Решение 1: Открывать файл для записи только тогда, когда есть что писать
Не открывай "w" заранее. Собери все данные в памяти, и только при корректном выходе (не по сигналу!) — запиши.
✅ Решение 2: Обрабатывай сигнал и не записывай, если не надо
Добавь флаг, который скажет, нужно ли сохранять данные.
✅ Пример безопасного кода:
🔐 Почему теперь безопасно?
- Файл не открывается на запись, пока не пришло время.
- При
Ctrl+C:fgets(stdin)прерывается → выход из цикла.- Устанавливается
should_save = 1. - Программа не падает, а идёт к сохранению.
- Файл открывается, записывается, закрывается.
- Даже если во время записи прилетит ещё один
Ctrl+C— можно защититься (см. ниже).
✅ Дополнительная защита: блокировка повторных сигналов
Теперь:
- Первый Ctrl+C — корректное завершение.
- Второй Ctrl+C — аварийное завершение (если зависло).
🛡️ Ещё лучше: использовать atexit()
Тогда даже при exit() данные сохранятся.
📌 Вывод
Файл становится 0 байт, потому что:
- Ты открываешь его в режиме
"w"→ он очищается сразу. - Программа не успевает записать и не успевает закрыть → данные теряются.
✅ Что делать:
- Не открывай
"w"заранее. - Собирай данные в памяти.
- Пиши только в конце, и только если нужно.
- Всегда вызывай
fclose(). - Используй флаг
should_saveиatexit()для надёжности.
Если пришлёшь свой код — могу показать, как его подправить строчка в строчку.
Комментариев нет:
Отправить комментарий