Bir işlem ne zaman SIGABRT (sinyal 6) alır?


203

Bir işlemin C ++ 'da SIGABRT aldığı senaryolar nelerdir? Bu sinyal her zaman süreç içinden mi geliyor yoksa bu sinyal bir süreçten diğerine gönderilebilir mi?

Bu sinyali hangi işlemin gönderdiğini belirlemenin bir yolu var mı?


3
Birkaç yol var. Programı yazdıysanız, en kolay yol, SIGABRT için bu bilgiyi basan ve geri dönmeden önce akışlarını temizleyen bir sinyal işleyici kaydetmektir. İkinci en kolay yol programı strace içinde çalıştırmaktır. Üçüncü en kolay yol, programın çöktüğünde bir çekirdek dosya oluşturmasını sağlamak ve çekirdek dökümü yoluyla bulmaktır.
Part Atışı

Yanıtlar:


196

abort()çağıran sürece SIGABRTsinyal gönderir, abort()temelde bu şekilde çalışır.

abort()genellikle dahili bir hatayı veya ciddi şekilde bozulmuş bir kısıtlamayı tespit eden kütüphane işlevleri tarafından çağrılır. Örneğin , iç yapıları yığın taşması nedeniyle hasar görürse malloc()arayacaktır abort().


27
Benim için çoğu durumda SIGABRT tarafından gönderilen libcaramaya çalışıyorum free()olmayan bir başlatıldı / bozuk pointer üzerinde
grandrew

Eğer kod içinde bir yerde, yapıcı içinde gömülü saf sanal fonksiyon çağrısı varsa, bu da SIGABRT sinyali ile sonuçlanabilir? Ben saf bir sanal çağrı olduğunu belirten bir hata görüyorum soruyorum ve sonraki satır bana bir SIGABRT mesajı verir ve uygulama ya çöküyor ya da işletim sistemi tarafından kapatılır. Teşekkürler.
Hrvoje

2
MacOS'ta, yaklaşık 1000 dosya tanıtıcısını kapatmadan açmak için SIGABRT'yi aldık. Alay etmek yerine, testlerimiz dosyayı daha genel bir okuyucu türüyle soyutladı, Close()yöntemi olmayan , bu yüzden unutuldu. Büyük kapsama alanı olsa vardı. : rolleyes:
Zyl

52

SIGABRTCiddi hatalar durumunda libc ve diğer kütüphaneler tarafından programı iptal etmek için yaygın olarak kullanılır. Örneğin, glibc, SIGABRTalgılanan çift serbest veya diğer yığın bozulmaları durumunda bir gönderir .

Ayrıca, çoğu assertuygulama SIGABRTbaşarısız bir iddiada kullanılır.

Ayrıca, SIGABRTdiğer sinyaller gibi diğer işlemlerden de gönderilebilir. Elbette, gönderme işleminin aynı kullanıcı veya kök olarak çalışması gerekir.


49

kill(2)Arayüzü kullanarak herhangi bir işleme herhangi bir sinyal gönderebilirsiniz :

kill -SIGABRT 30823

30823 dashbaşlattığım bir süreçti, bu yüzden öldürmek istediğim süreci kolayca bulabildim.

$ /bin/dash
$ Aborted

AbortedÇıkış nasıl görünüşte olan dashbir SIGABRT bildirir.

Bu kullanarak herhangi sürecine doğrudan gönderilebilir kill(2)ya da bir süreç aracılığıyla kendisine sinyali gönderebilir assert(3), abort(3)ya da raise(3).


17

Genellikle bellek ayırmayla ilgili bir sorun olduğunda olur.

Programım negatif boyutlu bir dizi ayırmaya çalışırken bana oldu.


14

C ++ durumunda başka bir basit neden daha var.

std::thread::~thread{
    if((joinable ())
        std::terminate ();
}

yani iş parçacığının kapsamı sona erdi ancak aramayı da unuttunuz

thread::join();

veya

thread::detach();

7

GNU libc, /dev/ttyaramadan önce bazı ölümcül koşullarla ilgili bilgileri yazdırır abort()(daha sonra tetiklenir SIGABRT), ancak programınızı bir hizmet olarak çalıştırıyorsanız veya gerçek bir terminal penceresinde çalıştırmıyorsanız, bu mesaj kaybolabilir, çünkü tty mesajları görüntülemek için.

/ Dev / tty yerine stderr'e yazmak için libc'yi yeniden yönlendirmeyle ilgili yazımı görün:

/ Dev / tty'den yönlendirme yapan libc hata mesajlarını yakalama


4

Sürecin kendisinden SIGABRT aldığı bir durum: Hrvoje, kürtaj üreten ctordan çağrılan gömülü saf sanaldan bahsetti, bunun için bir örnek oluşturdum. Burada d inşa edildiğinde, önce temel A sınıfı ctorunu çağırır ve ibrenin içine kendi kendine geçer. a ctor, d henüz oluşturulmadığından tablo geçerli işaretçiyle doldurulmadan önce saf sanal yöntemi çağırır.

#include<iostream>
using namespace std;
class A {
public:
 A(A *pa){pa->f();}
 virtual void f()=0;
};
class D : public A {
public:
 D():A(this){}
 virtual void f() {cout<<"D::f\n";}
};
int main(){
 D d;
 A *pa = &d;
 pa->f();
 return 0;
}

derleme: g ++ -o aa aa.cpp

ulimit -c sınırsız

run: ./aa

pure virtual method called
terminate called without an active exception
Aborted (core dumped)

Şimdi çekirdek dosyayı hızlıca görelim ve SIGABRT'nin gerçekten çağrıldığını doğrulayalım:

gdb aa core

bkz.

i r
rdx            0x6      6
rsi            0x69a    1690
rdi            0x69a    1690
rip            0x7feae3170c37

kodu kontrol et:

disas 0x7feae3170c37

mov    $0xea,%eax  = 234  <- this is the kill syscall, sends signal to process
syscall   <-----

http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

234 sys_tgkill pid_t tgid pid_t pid int sig = 6 = SIGABRT

:)


2

Benim durumumda, dizinin uzunluğuna eşit bir dizindeki bir dizideki bir girdiden kaynaklanıyordu.

string x[5];

for(int i=1; i<=5; i++){

    cin>>x[i];

}

Mevcut olmayan x [5] 'e erişiliyor.


1

"@Sarnold" u belirtildiği gibi, herhangi bir süreç başka bir sürece sinyal gönderebilir, bu nedenle bir süreç SIGABORT'u diğer sürece gönderebilir ve bu durumda alma işlemi, kendi ayarlaması nedeniyle gelip gelmediğini ayırt edemez. bellek vb, ya da başkasının "tek noktaya", göndermek.

Çalıştığım sistemlerden birinde, işlemin kalp atışı vererek bazı görevlerden çıkıp çıkmadığını gerçekten tespit eden bir kilitlenme dedektörü var. Değilse, işlemin kilitlenme durumunda olduğunu bildirir ve SIGABORT'u ona gönderir.

Bu olası adayı, sorulan soruya referansla paylaşmak istedim.


0

Cevabımı rekabetçi bir programlama (cp) perspektifinden vereceğim , ancak diğer alanlar için de geçerlidir.

Birçok kez cp yaparken, kısıtlamalar oldukça büyük.

Örneğin : N, M, QBöyle değişkenlerle bir sorum vardı 1 ≤ N, M, Q < 10^5.

Ben çıkıyordu hatam boyutu dizisi tamsayı bir 2D ilan oldu 10000 x 10000içinde C++ve mücadele SIGABRTneredeyse 2 gün boyunca Codechef de hata.

Şimdi, eğer hesaplarsak:

Tipik bir tamsayı boyutu: 4 bayt

Dizimizdeki hücre sayısı: 10000 x 10000

Toplam boyut (bayt cinsinden): 400000000 bayt = 4 * 10 ^ 8 ≈ 400 MB

Bu tür sorulara yönelik çözümleriniz PC'nizde çalışacaktır (her zaman değil), bu boyutu karşılayabilir.

Ancak kodlama sitelerindeki kaynaklar (çevrimiçi hakimler) birkaç KB ile sınırlıdır.

Bu nedenle, SIGABRThata ve benzeri hatalar.

Sonuç:

Bu tür sorularda, bir dizi veya vektör veya bu boyutta başka bir DS bildirmemeliyiz, ancak görevimiz algoritmamızı onlarsız (DS) veya daha az bellekle çalışacak kadar verimli hale getirmektir.

Not : Bu hatanın başka nedenleri olabilir; yukarıda onlardan biriydi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.