사용자 정의 소멸자가있는 클래스가 있습니다. 클래스가 처음에 인스턴스화 된 다음 프로그램이 실행되는 동안 SIGINT가 발행되면 (유닉스에서 CTRL + C 사용) 소멸자가 호출됩니까? SIGSTP (유닉스에서 CTRL + Z)의 동작은 무엇입니까?SIGINT 또는 SIGSTP가 발행되면 소멸자가 호출됩니까?
답변
기본적으로 대부분의 신호로 인해 프로그램이 즉각적이고 비정상적으로 종료됩니다.
그러나 대부분의 신호에 대한 기본 동작을 쉽게 변경할 수 있습니다. 이 프로그램을 누르 제어-C를 실행하면
#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;
}
, 당신은 단어 "소멸자"을 참조해야합니다
이 코드는 모든 일반적인 소멸자를 호출을 포함하여, 일반적으로 신호 종료 프로그램을 만드는 방법을 보여줍니다 인쇄. 시그널 핸들러 함수 (got_signal)는 실제로 무엇을하고 있는지 알지 못하는 한, 플래그를 설정하고 조용하게 돌아 오는 것 이외의 다른 일을해서는 안된다는 것을 알아 두십시오.
대부분의 신호는 위의 그림과 같이 catch 가능하지만 SIGKILL은 제어 할 수 없습니다. SIGKILL은 사용자가 프로세스를 정지시킬 수있는 SIGSTOP이 아니라 runaway 프로세스를 종료하는 마지막 수단입니다. 원하는 경우 SIGTSTP (control-Z)를 잡을 수는 있지만 신호에 대한 관심 만이 소멸자 동작 인 경우에는 필요하지 않습니다. 결국 컨트롤 -Z에서 프로세스가 깨어나고 계속 실행되며 모든 소멸자가 효과를 발휘하여 정상적으로 종료됩니다.
이러한 신호를 직접 처리하지 않으면 아니오, 소멸자가 호출되지 않습니다. 그러나 운영 체제는 프로그램이 종료 될 때 사용한 모든 자원을 회수합니다.
신호를 직접 처리하려면 sigaction
표준 라이브러리 기능을 확인해보십시오.
OS 소유의 자원 재생. 응용 프로그램에는 다른 자원이 있으며 일반적으로 올바르게 닫히는 방법으로 포장됩니다 (그렇지 않으면 제대로 종료되지 않은 파일과 같은 손상된 자원이 생깁니다). –
의 그것을 시도하자 다음
#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
이 전송 될 때까지 프로세스를 일시 중지합니다.
IIRC의 올바른 유형의'quit'은'volatile std :: sig_atomic_t'이어야합니다. 이런 목적으로'bool'을 사용하는 것은 UB입니다. – MSalters
@MSalters : 맞습니다. sigaction() 전에 sigfillset() 호출을 포함시켜야합니다. 아마도 sig_atomic_t보다 훨씬 좋을 것입니다. bool을 사용하면 추가 신호가 신호 처리기 인터럽트를 차단할 때보다 익숙하고 완벽하게 안전합니다. 내 예제 코드를 수정했습니다. –
사실이 코드는'quit = false' 라인에'delete function 사용'오류가 있습니다. 'quit = false' 대신'quit (false)'를해야합니다. 또한이 코드가 Windows에서 작동하지 않는다는 점에 유의할 가치가 있습니다. 당신은'SetConsoleCtrlHandler()'를 사용해야합니다. – Timmmm