четверг, 16 июля 2026 г.

Sig int

 Спасибо за уточнение — теперь картина полностью ясна.

У тебя примерно такая логика:

И вот что происходит при Ctrl+C:

  • Программа находится в fgets(stdin) — ждёт ввода.
  • Нажимаешь Ctrl+C → приходит SIGINT.
  • fgets() прерывается и возвращает NULL.
  • Цикл завершается.
  • Программа идёт дальше → открывает файл в режиме "w" → начинает запись.
  • НО В этот момент приходит сигнал снова или программа аварийно завершаетсяfclose() не вызывается → файл повреждается или обнуляется.

🔍 Почему файл становится 0 байт?

Потому что:

  1. Ты открываешь файл в режиме "w":
  2. Даже если программа не успела ничего записать, файл уже пустой.
  3. Если после этого она аварийно завершается (например, из-за повторного 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" → он очищается сразу.
  • Программа не успевает записать и не успевает закрыть → данные теряются.

✅ Что делать:

  1. Не открывай "w" заранее.
  2. Собирай данные в памяти.
  3. Пиши только в конце, и только если нужно.
  4. Всегда вызывай fclose().
  5. Используй флаг should_save и atexit() для надёжности.

Если пришлёшь свой код — могу показать, как его подправить строчка в строчку.

Комментариев нет:

Отправить комментарий