2010-11-22 17 views
29

Kullanıcı tanımlı bir yok edici ile bir sınıfım var. Eğer sınıf başlangıçta örneklenmişse ve program çalıştırılırken SIGINT (Unix'te CTRL + C kullanılarak) verilirse, yıkıcı çağrılacak mı? SIGSTP (unix'te CTRL + Z) için davranış nedir?SIGINT veya SIGSTP yayınlanmışsa yıkıcı denir mi?

cevap

24

Hayır, varsayılan olarak, çoğu sinyal programınızın ani ve anormal çıkmasına neden olur. Ancak çoğu sinyal için varsayılan davranışı kolayca değiştirebilirsiniz. Eğer bu program ve pres kontrolü-C çalıştırırsanız

#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; 
} 

, sen kelime "yıkıcı" görmelisiniz:

Bu kod her zamanki yıkıcı çağıran dahil normalde bir sinyal çıkışına program nasıl gösterir basılmış. Sinyal işleyicinizin (got_signal) işlevlerinin, yaptığınız işi gerçekten bilmediğiniz sürece, bir bayrağın ayarlanması ve sessizce geri dönmesi dışında, nadiren herhangi bir iş yapması gerektiğini unutmayın.

Çoğu sinyal yukarıda gösterildiği gibi yerleştirilebilir, fakat SIGKILL değil, üzerinde herhangi bir kontrole sahip değilsiniz çünkü SIGKILL, bir işlemi soğuk bir prosesi dondurmaya izin veren SIGSTOP'u yok etmeyi amaçlayan son çukur bir yöntemdir. Eğer istenirse SIGTSTP'yi (kontrol-Z) yakalayabileceğinizi göz önünde bulundurunuz, fakat eğer sinyallerdeki tek ilginiz yıkıcı davranışsa, gerek yok çünkü bir kontrol-Z'den sonra süreç uyandı, çalışmaya devam edecek ve etkisiz tüm yıkıcılar ile normal olarak çıkacak.

+5

IIRC, 'quit' türünün doğru türü 'volatile std :: sig_atomic_t' olmalıdır. Bu amaçla 'bool' kullanmak UB'dir. – MSalters

+0

@MSalters: Sağlam sig_atomic_t'den daha iyi olan sigaction() çağrısından önce sigfillset() çağrısı içermeliydim. Ek sinyallerin sinyal işleyicisini kesintiye uğratması engellendiğinde, bir boole kullanmak daha tanıdık ve mükemmel derecede güvenlidir. Örnek kodumu düzenledim, teşekkürler. –

+2

Aslında bu kodla ilgili bir hata alıyorum: 'quit = false 'satırı için' delete function kullanımı'. "Çık" (false) yerine "çıkmak (yanlış)" yapmak zorundasınız. Ayrıca bu kodun Windows üzerinde çalışmadığına dikkat edin; SetConsoleCtrlHandler() 'i kullanmalısınız. – Timmmm

8

Bu sinyalleri kendiniz işlemezseniz, o zaman, hayır, yok ediciler çağırılmaz. Ancak, işletim sistemi, programınızın sona erdiğinde kullandığı kaynakları geri alacaktır.

Sinyalleri kendiniz işlemek isterseniz, sigaction standart kitaplık işlevine göz atmayı düşünün.

+3

İşletim sistemi tarafından sahip olunan kaynakların geri alınması. Bir uygulama içinde başka başka kaynaklar da vardır ve bunlar genellikle doğru bir şekilde kapatılmaları gerektiği şekilde sarılırlar (aksi halde bozuk kaynaklar (düzgün bir şekilde sonlandırılmayan bir dosya gibi)). –

6

Şunu deneyelim: o zaman

#include <stdio.h> 
#include <unistd.h> 

class Foo { 
public: 
    Foo() {}; 
    ~Foo() { printf("Yay!\n"); } 
} bar; 

int main(int argc, char **argv) { 
    sleep(5); 
} 

Ve:

$ g++ -o test ./test.cc 
$ ./test 
^C 
$ ./test 
Yay! 

Yani Korkmuyorum, bunu yakalamak gerekecek.

SIGSTOP'a gelince, yakalanamaz ve bir SIGCONT gönderilinceye kadar işlemi duraklatır.