Quali sono gli scenari in cui un processo ottiene un SIGABRT in C ++? Questo segnale proviene sempre dall'interno del processo o può essere inviato da un processo all'altro?
C'è un modo per identificare quale processo sta inviando questo segnale?
Quali sono gli scenari in cui un processo ottiene un SIGABRT in C ++? Questo segnale proviene sempre dall'interno del processo o può essere inviato da un processo all'altro?
C'è un modo per identificare quale processo sta inviando questo segnale?
Risposte:
abort()
invia il SIGABRT
segnale al processo di chiamata , ecco come abort()
funziona sostanzialmente.
abort()
di solito viene chiamato dalle funzioni di libreria che rilevano un errore interno o un vincolo gravemente rotto. Ad esempio malloc()
chiamerà abort()
se le sue strutture interne sono danneggiate da un overflow dell'heap.
libc
tentando di chiamare free()
un puntatore non inizializzato / danneggiato
Close()
metodo, quindi è stato dimenticato. Aveva una grande copertura però. : carrelli:
SIGABRT
è comunemente usato da libc e da altre librerie per interrompere il programma in caso di errori critici. Ad esempio, glibc invia un SIGABRT
caso di corruzione dell'heap rilevata double-free o di altro tipo.
Inoltre, la maggior parte delle assert
implementazioni si avvale SIGABRT
in caso di affermazione fallita.
Inoltre, SIGABRT
può essere inviato da qualsiasi altro processo come qualsiasi altro segnale. Naturalmente, il processo di invio deve essere eseguito come lo stesso utente o root.
È possibile inviare qualsiasi segnale a qualsiasi processo utilizzando l' kill(2)
interfaccia:
kill -SIGABRT 30823
30823 è stato un dash
processo che ho avviato, quindi ho potuto facilmente trovare il processo che volevo uccidere.
$ /bin/dash
$ Aborted
L' Aborted
output è apparentemente comedash
riporta un SIGABRT.
Può essere inviato direttamente a qualsiasi processo che utilizza kill(2)
, o un processo può inviare il segnale a se stesso tramite assert(3)
, abort(3)
o raise(3)
.
C'è un'altra semplice causa in caso di c ++.
std::thread::~thread{
if((joinable ())
std::terminate ();
}
cioè l'ambito del thread è terminato ma ti sei dimenticato di chiamare
thread::join();
o
thread::detach();
GNU libc stamperà le informazioni /dev/tty
relative ad alcune condizioni fatali prima di chiamare abort()
(che quindi si innesca SIGABRT
), ma se stai eseguendo il tuo programma come servizio o altrimenti non in una finestra terminale reale, questi messaggi potrebbero andare persi, perché non c'è tty per visualizzare i messaggi.
Vedi il mio post sul reindirizzamento di libc per scrivere su stderr invece di / dev / tty:
Cattura dei messaggi di errore libc, reindirizzamento da / dev / tty
Un caso in cui il processo prende SIGABRT da solo: Hrvoje ha menzionato un essere virtuale puro sepolto chiamato da ctor che genera un abort, ho ricreato un esempio per questo. Qui quando si deve costruire d, prima chiama la sua classe di base A ctor e passa il puntatore all'interno di se stesso. il ctor chiama puro metodo virtuale prima che la tabella fosse riempita con un puntatore valido, perché d non è ancora stato costruito.
#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;
}
compilare: g ++ -o aa aa.cpp
ulimit -c illimitato
corsa: ./aa
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
ora consente di vedere rapidamente il file principale e di confermare che SIGABRT è stato effettivamente chiamato:
gdb aa core
vedi regs:
i r
rdx 0x6 6
rsi 0x69a 1690
rdi 0x69a 1690
rip 0x7feae3170c37
codice di controllo:
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
:)
Come "@sarnold", opportunamente sottolineato, qualsiasi processo può inviare segnali a qualsiasi altro processo, quindi, un processo può inviare SIGABORT ad un altro processo e in quel caso il processo di ricezione non è in grado di distinguere se il suo arrivo a causa della propria modifica di memoria ecc., o qualcun altro ha "unicastly", inviare ad esso.
In uno dei sistemi su cui ho lavorato c'è un rilevatore di deadlock che in realtà rileva se il processo sta uscendo da qualche compito dando il battito cardiaco o meno. In caso contrario, dichiara che il processo è in stato di deadlock e invia SIGABORT ad esso.
Volevo solo condividere questa prospettiva con riferimento alla domanda posta.
Darò la mia risposta dal punto di vista della programmazione competitiva (cp) , ma si applica anche ad altri settori.
Molte volte mentre si fa cp, i vincoli sono piuttosto grandi.
Ad esempio : avevo una domanda con una variabile N, M, Q
tale 1 ≤ N, M, Q < 10^5
.
L'errore facevo era io dichiarata 2D intero array di dimensione 10000 x 10000
in C++
e lottato con ilSIGABRT
errore in Codechef per quasi 2 giorni.
Ora, se calcoliamo:
Dimensione tipica di un numero intero: 4 byte
Numero di celle nel nostro array: 10000 x 10000
Dimensione totale (in byte): 400000000 byte = 4 * 10 ^ 8 ≈ 400 MB
Le tue soluzioni a tali domande funzioneranno sul tuo PC (non sempre) in quanto possono permettersi queste dimensioni.
Ma le risorse nei siti di codifica (giudici online) sono limitate a pochi KB.
Quindi, l' SIGABRT
errore e altri errori simili.
Conclusione:
In tali domande, non dovremmo dichiarare un array o un vettore o qualsiasi altro DS di queste dimensioni, ma il nostro compito è rendere il nostro algoritmo così efficiente da funzionare senza di essi (DS) o con meno memoria.
PS : potrebbero esserci altri motivi per questo errore; sopra c'era uno di questi.