c++ - signal - sigtstp
¿Cuándo un proceso obtiene SIGABRT(señal 6)? (8)
¿Cuáles son los escenarios donde un proceso obtiene un SIGABRT en C ++? ¿Esta señal siempre proviene del proceso o puede enviarse esta señal de un proceso a otro?
¿Hay alguna manera de identificar qué proceso está enviando esta señal?
En mi caso, fue debido a una entrada en una matriz en un índice igual a la longitud de la matriz.
string x[5];
for(int i=1; i<=5; i++){
cin>>x[i];
}
x [5] se está accediendo que no está presente.
Hay otra causa simple en el caso de c ++.
std::thread::~thread{
if((joinable ())
std::terminate ();
}
es decir, el alcance del hilo terminó pero olvidó llamar
thread::join();
o
thread::detach();
La libc de GNU imprimirá información en /dev/tty
respecto a algunas condiciones fatales antes de llamar a abort()
(que luego desencadena SIGABRT
), pero si está ejecutando su programa como un servicio o no en una ventana de terminal real, estos mensajes puede perderse, porque no hay tty para mostrar los mensajes.
Ver mi publicación sobre cómo redirigir libc para escribir en stderr en lugar de / dev / tty:
Captura de mensajes de error de libc, redirigiendo desde / dev / tty
Puede enviar cualquier señal a cualquier proceso utilizando la interfaz kill(2)
:
kill -SIGABRT 30823
30823 fue un proceso de dash
que comencé, así que pude encontrar fácilmente el proceso que quería matar.
$ /bin/dash
$ Aborted
El resultado Aborted
es aparentemente cómo dash
informa un SIGABRT.
Se puede enviar directamente a cualquier proceso utilizando kill(2)
, o un proceso puede enviar la señal a sí mismo a través de assert(3)
, abort(3)
o raise(3)
.
Suele suceder cuando hay un problema con la asignación de memoria.
Me pasó a mí cuando mi programa intentaba asignar una matriz con tamaño negativo.
Un caso cuando el proceso obtiene SIGABRT de sí mismo: Hrvoje mencionó acerca de un ser virtual puro enterrado llamado desde ctor que genera un aborto, recreé un ejemplo para esto. Aquí cuando se va a construir d, primero llama a su clase base A ctor, y pasa el puntero interno a sí mismo. el Actor llama al método virtual puro antes de que la tabla se llenara con un puntero válido, porque d aún no está construido.
#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;
}
compilar: g ++ -o aa aa.cpp
ulimit -c ilimitado
ejecutar: ./aa
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
ahora veamos rápidamente el archivo central y validemos que efectivamente se llamó SIGABRT:
gdb aa core
ver reglas:
i r
rdx 0x6 6
rsi 0x69a 1690
rdi 0x69a 1690
rip 0x7feae3170c37
Código de verificación:
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
:)
SIGABRT
es comúnmente utilizado por libc y otras bibliotecas para abortar el programa en caso de errores críticos. Por ejemplo, glibc envía un SIGABRT
en caso de una corrupción detectada de doble libre u otra corrupción de montón.
Además, la mayoría de las implementaciones de " assert
" hacen uso de SIGABRT
en caso de una afirmación fallida.
Además, SIGABRT
se puede enviar desde cualquier otro proceso como cualquier otra señal. Por supuesto, el proceso de envío debe ejecutarse como el mismo usuario o raíz.
abort()
envía al proceso de llamada la señal SIGABRT
, así es como funciona abort()
básicamente.
abort()
suele ser llamado por las funciones de la biblioteca que detectan un error interno o alguna restricción gravemente dañada. Por ejemplo, malloc()
llamará a abort()
si sus estructuras internas están dañadas por un desbordamiento de pila.