У меня есть класс с определяемым пользователем деструктором. Если класс был создан изначально, а затем выдается сигнал SIGINT (с использованием CTRL+C в unix) во время работы программы, будет ли вызван деструктор? Как ведет себя SIGSTP (CTRL + Z в unix)?
Вызывается ли деструктор, если выдается SIGINT или SIGSTP?
Ответы (3)
Нет, по умолчанию большинство сигналов вызывают немедленный аварийный выход из вашей программы.
Однако вы можете легко изменить поведение по умолчанию для большинства сигналов.
Этот код показывает, как заставить сигнал выйти из вашей программы в обычном режиме, включая вызов всех обычных деструкторов:
#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstring>
#include <atomic>
std::atomic<bool> quit(false); // signal flag
void got_signal(int)
{
quit.store(true);
}
class Foo
{
public:
~Foo() { std::cout << "destructor\n"; }
};
int main(void)
{
struct sigaction sa;
memset( &sa, 0, sizeof(sa) );
sa.sa_handler = got_signal;
sigfillset(&sa.sa_mask);
sigaction(SIGINT,&sa,NULL);
Foo foo; // needs destruction before exit
while (true)
{
// do real work here...
sleep(1);
if( quit.load() ) break; // exit normally after SIGINT
}
return 0;
}
Если вы запустите эту программу и нажмете control-C, вы должны увидеть напечатанное слово «destructor». Имейте в виду, что ваши функции обработчика сигналов (got_signal) редко должны выполнять какую-либо работу, кроме установки флага и тихого возврата, если вы действительно не знаете, что делаете.
Большинство сигналов можно перехватить, как показано выше, но не SIGKILL, вы не можете его контролировать, потому что SIGKILL — это последний метод уничтожения неконтролируемого процесса, а не SIGSTOP, который позволяет пользователю заморозить процесс в холодном состоянии. Обратите внимание, что вы можете поймать SIGTSTP (control-Z), если хотите, но вам это не нужно, если вас интересует только поведение деструктора, потому что в конечном итоге после control-Z процесс будет разбужен, продолжит работу и завершится нормально со всеми действующими деструкторами.
quit
должен быть volatile std::sig_atomic_t
. Это UB использовать bool
для этой цели.
- person MSalters; 23.11.2010
use of deleted function
для строки quit = false
. Вы должны сделать quit(false)
вместо quit = false
. Также стоит отметить, что этот код не работает в Windows; вы должны использовать SetConsoleCtrlHandler()
.
- person Timmmm; 03.02.2016
Если вы сами не обрабатываете эти сигналы, то нет, деструкторы не вызываются. Однако операционная система вернет все ресурсы, использованные вашей программой, когда она завершится.
Если вы хотите самостоятельно обрабатывать сигналы, рассмотрите возможность использования стандартной библиотечной функции sigaction
.
Давай попробуем:
#include <stdio.h>
#include <unistd.h>
class Foo {
public:
Foo() {};
~Foo() { printf("Yay!\n"); }
} bar;
int main(int argc, char **argv) {
sleep(5);
}
А потом:
$ g++ -o test ./test.cc
$ ./test
^C
$ ./test
Yay!
Так что, боюсь, нет, вам придется его поймать.
Что касается SIGSTOP
, его нельзя перехватить, и процесс приостанавливается до тех пор, пока не будет отправлено SIGCONT
.