Kapan suatu proses mendapatkan SIGABRT (sinyal 6)?


202

Apa skenario di mana proses mendapatkan SIGABRT di C ++? Apakah sinyal ini selalu datang dari dalam proses atau dapatkah sinyal ini dikirim dari satu proses ke proses lainnya?

Apakah ada cara untuk mengidentifikasi proses mana yang mengirim sinyal ini?


3
Ada beberapa cara. Cara termudah, jika Anda menulis programnya, adalah mendaftarkan penangan sinyal untuk SIGABRT yang mencetak informasi itu dan menyiram alirannya sebelum kembali. Cara termudah kedua adalah menjalankan program dalam strace. Cara termudah ketiga adalah memastikan program menghasilkan file inti ketika crash, dan mencari tahu melalui dump inti.
Parthian Shot

Jawaban:


195

abort()mengirimkan proses panggilan SIGABRTsinyal, ini abort()pada dasarnya cara kerjanya.

abort()biasanya dipanggil oleh fungsi pustaka yang mendeteksi kesalahan internal atau beberapa kendala serius rusak. Misalnya malloc()akan memanggil abort()jika struktur internalnya rusak oleh heap overflow.


27
bagi saya dalam banyak kasus SIGABRT dikirim dengan libcmencoba memanggil free()penunjuk yang tidak diinisialisasi / rusak
grandrew

Jika saya memiliki suatu tempat di dalam kode, terkubur panggilan fungsi virtual murni dari dalam konstruktor, dapatkah itu juga berakhir dengan sinyal SIGABRT? Saya bertanya ketika saya melihat kesalahan yang menyatakan bahwa saya memiliki panggilan virtual murni, dan baris berikutnya memberi saya pesan SIGABRT dan aplikasi itu crash atau ditutup oleh sistem operasi. Terima kasih.
Hrvoje

2
Di MacOS, kami mendapatkan SIGABRT untuk membuka sekitar 1000 file menangani tanpa menutupnya. Alih-alih mengejek, pengujian kami mengabstraksi file dengan tipe pembaca yang lebih umum, yang tidak memiliki Close()metode, jadi itu terlupakan. Memiliki cakupan yang bagus. : rolleyes:
Zyl

52

SIGABRTumumnya digunakan oleh libc dan perpustakaan lain untuk membatalkan program jika terjadi kesalahan kritis. Sebagai contoh, glibc mengirimkan SIGABRTdalam kasus korupsi tumpukan ganda yang terdeteksi atau bebas.

Juga, sebagian besar assertimplementasi memanfaatkan SIGABRTjika pernyataan gagal.

Selanjutnya, SIGABRTdapat dikirim dari proses lain seperti sinyal lainnya. Tentu saja, proses pengiriman perlu dijalankan sebagai pengguna atau root yang sama.


49

Anda dapat mengirim sinyal apa pun ke proses apa pun menggunakan kill(2)antarmuka:

kill -SIGABRT 30823

30823 adalah dashproses yang saya mulai, jadi saya dapat dengan mudah menemukan proses yang ingin saya bunuh.

$ /bin/dash
$ Aborted

The Abortedoutput rupanya bagaimanadash melaporkan SIGABRT a.

Hal ini dapat dikirim langsung ke setiap proses menggunakan kill(2), atau suatu proses dapat mengirim sinyal untuk dirinya sendiri melalui assert(3), abort(3)atau raise(3).


17

Ini biasanya terjadi ketika ada masalah dengan alokasi memori.

Itu terjadi pada saya ketika program saya mencoba mengalokasikan array dengan ukuran negatif.


14

Ada penyebab sederhana lain dalam kasus c ++.

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

yaitu ruang lingkup utas berakhir tetapi Anda lupa menelepon juga

thread::join();

atau

thread::detach();

7

GNU libc akan mencetak informasi /dev/ttytentang beberapa kondisi fatal sebelum ia dipanggil abort()(yang kemudian memicu SIGABRT), tetapi jika Anda menjalankan program Anda sebagai layanan atau tidak dalam jendela terminal nyata, pesan ini dapat hilang, karena tidak ada tty untuk menampilkan pesan.

Lihat posting saya di redirect libc untuk menulis ke stderr bukannya / dev / tty:

Menangkap pesan kesalahan libc, mengalihkan dari / dev / tty


4

Sebuah kasus ketika proses mendapatkan SIGABRT dari dirinya sendiri: Hrvoje menyebutkan tentang virtual murni yang terkubur yang dipanggil dari ctor yang membuat abort, saya menciptakan contoh untuk ini. Di sini ketika d akan dibangun, pertama-tama memanggil ctor kelas dasar A, dan meneruskan pointer ke dalam dirinya sendiri. a ctor memanggil metode virtual murni sebelum tabel diisi dengan pointer yang valid, karena d belum dibangun.

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

kompilasi: g ++ -o aa aa.cpp

ulimit -c tidak terbatas

jalankan: ./aa

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

sekarang mari kita cepat melihat file inti, dan memvalidasi bahwa SIGABRT memang dipanggil:

gdb aa core

lihat regs:

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

periksa kode:

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

Dalam kasus saya, itu disebabkan oleh input dalam array pada indeks yang sama dengan panjang array.

string x[5];

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

    cin>>x[i];

}

x [5] sedang diakses yang tidak ada.


1

Seperti "@sarnold", dengan tepat menunjukkan, setiap proses dapat mengirim sinyal ke proses lain, karenanya, satu proses dapat mengirim SIGABORT ke proses lain & dalam hal ini proses penerima tidak dapat membedakan apakah itu datang karena penyesuaian sendiri dari tweaker sendiri. memori dll, atau orang lain memiliki "unicastly", kirim ke sana.

Dalam salah satu sistem saya bekerja ada satu kebuntuan detektor yang sebenarnya mendeteksi jika proses keluar dari suatu tugas dengan memberikan detak jantung atau tidak. Jika tidak, maka dinyatakan prosesnya dalam kondisi menemui jalan buntu dan mengirim SIGABORT ke sana.

Saya hanya ingin membagikan calon ini dengan referensi pertanyaan yang diajukan.


0

Saya akan memberikan jawaban saya dari perspektif pemrograman kompetitif (cp) , tetapi itu berlaku untuk domain lain juga.

Banyak kali saat melakukan cp, kendala cukup besar.

Sebagai contoh : Saya punya pertanyaan dengan variabel N, M, Qseperti itu 1 ≤ N, M, Q < 10^5.

Kesalahan saya membuat adalah saya menyatakan 2D array integer dari ukuran 10000 x 10000di C++dan berjuang denganSIGABRT kesalahan pada Codechef selama hampir 2 hari.

Sekarang, jika kita menghitung:

Ukuran khas bilangan bulat: 4 byte

Jumlah sel dalam array kami: 10.000 x 10.000

Ukuran total (dalam byte): 400000000 byte = 4 * 10 ^ 8 ≈ 400 MB

Solusi Anda untuk pertanyaan-pertanyaan seperti itu akan bekerja pada PC Anda (tidak selalu) karena mampu membayar ukuran ini.

Tetapi sumber daya di situs pengkodean (juri online) terbatas pada beberapa KB.

Oleh karena itu, SIGABRTkesalahan dan kesalahan lainnya.

Kesimpulan:

Dalam pertanyaan seperti itu, kita tidak boleh mendeklarasikan array atau vektor atau DS lain dari ukuran ini, tetapi tugas kita adalah membuat algoritma kita sedemikian efisien sehingga berfungsi tanpa mereka (DS) atau dengan memori lebih sedikit.

PS : Mungkin ada alasan lain untuk kesalahan ini; di atas adalah salah satunya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.