Освоение обработки сигналов в C++: безопасное управление прерываниями и корректное завершение программы
Сигналы — это прерывания, которые операционная система передает процессу. Они могут привести к преждевременному завершению программы. Например, нажатие Ctrl+C в UNIX, Linux, macOS или Windows генерирует сигнал прерывания.
Не все сигналы можно перехватить, но существует список сигналов, которые программа может обрабатывать, выполняя соответствующие действия. Эти сигналы определены в заголовочном файле C++ <csignal>.
| № | Сигнал и описание |
|---|---|
| 1 | SIGABRT — аварийное завершение программы, например, вызов функции abort(). |
| 2 | SIGFPE — ошибочная арифметическая операция, такая как деление на ноль или переполнение. |
| 3 | SIGILL — обнаружение недопустимой инструкции. |
| 4 | SIGINT — получение интерактивного сигнала внимания (обычно Ctrl+C). |
| 5 | SIGSEGV — недопустимый доступ к памяти. |
| 6 | SIGTERM — запрос на завершение программы. |
Функция signal()
Библиотека обработки сигналов C++ предоставляет функцию signal для перехвата непредвиденных событий. Её синтаксис:
void (*signal(int sig, void (*func)(int)))(int);
Проще говоря, функция принимает два аргумента: номер сигнала (целое число) и указатель на функцию-обработчик.
Рассмотрим пример перехвата сигнала SIGINT с помощью signal(). Любой сигнал, который вы хотите отловить, нужно зарегистрировать, связав его с обработчиком.
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "Interrupt signal (" << signum << ") received.\n";
// очистка и закрытие ресурсов
exit(signum);
}
int main() {
// регистрация SIGINT и обработчика
signal(SIGINT, signalHandler);
while (true) {
cout << "Going to sleep...." << endl;
sleep(1);
}
return 0;
}
При компиляции и запуске программа будет выводить "Going to sleep...." каждую секунду. Нажмите Ctrl+C, чтобы прервать выполнение — программа перехватит сигнал и завершится с сообщением:
Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.
Функция raise()
Сигналы можно генерировать программно с помощью функции raise(), которая принимает номер сигнала:
int raise(int sig);
Аргумент sig может быть одним из: SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP.
Пример генерации сигнала внутри программы:
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "Interrupt signal (" << signum << ") received.\n";
exit(signum);
}
int main() {
int i = 0;
signal(SIGINT, signalHandler);
while (++i) {
cout << "Going to sleep...." << endl;
if (i == 3) {
raise(SIGINT);
}
sleep(1);
}
return 0;
}
Программа автоматически завершится после третьей итерации с выводом:
Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.
Язык C
- Понимание типов данных C++: основы, модификаторы и лучшие практики
- Освоение операторов C++: полное руководство с практическими примерами
- Комментарии в C++: лучшие практики для читаемого и поддерживаемого кода
- Шаблоны классов в C++: практическое руководство
- Работа с файлами в C: мастерство ввода-вывода с fopen, fprintf, fread и fseek
- Обработка исключений в C++: практические примеры try, catch, throw
- Обработка ошибок в C: лучшие практики и техники
- Язык программирования C++: обзор и ключевые особенности
- Константы и литералы в C++: типы, синтаксис и лучшие практики
- Полное руководство по операторам C++: типы, использование и лучшие практики