¿Cuáles son los escenarios en los que un proceso obtiene un SIGABRT en C ++? ¿Esta señal siempre proviene del proceso o puede enviarse de un proceso a otro?
¿Hay alguna manera de identificar qué proceso está enviando esta señal?
¿Cuáles son los escenarios en los que un proceso obtiene un SIGABRT en C ++? ¿Esta señal siempre proviene del proceso o puede enviarse de un proceso a otro?
¿Hay alguna manera de identificar qué proceso está enviando esta señal?
Respuestas:
abort()
envía la SIGABRT
señal al proceso de llamada , así es como abort()
funciona básicamente.
abort()
Por lo general, se llama mediante funciones de biblioteca que detectan un error interno o alguna restricción seriamente rota. Por ejemplo malloc()
, llamará abort()
si sus estructuras internas están dañadas por un desbordamiento del montón.
libc
intentar llamar free()
a un puntero no inicializado / dañado
Close()
método, por lo que se olvidó. Aunque tenía una gran cobertura. : rolleyes:
SIGABRT
es comúnmente usado por libc y otras bibliotecas para abortar el programa en caso de errores críticos. Por ejemplo, glibc envía unSIGABRT
en caso de que se detecte doble-libre u otros daños en el montón.
Además, la mayoría de las assert
implementaciones hacen uso deSIGABRT
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.
Puede enviar cualquier señal a cualquier proceso utilizando la kill(2)
interfaz:
kill -SIGABRT 30823
30823 fue un dash
proceso que comencé, por lo que pude encontrar fácilmente el proceso que quería matar.
$ /bin/dash
$ Aborted
La Aborted
salida es al parecer la forma dash
reporta un SIGABRT.
Puede ser enviado directamente a cualquier proceso que utiliza kill(2)
, o un proceso puede enviar la señal a sí mismo a través de assert(3)
, abort(3)
o raise(3)
.
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();
GNU libc imprimirá información /dev/tty
sobre algunas condiciones fatales antes de llamar abort()
(que luego se dispara SIGABRT
), pero si está ejecutando su programa como un servicio o no en una ventana de terminal real, este mensaje puede perderse, porque no hay tty para mostrar los mensajes.
Vea mi publicación sobre la redirección de libc para escribir en stderr en lugar de / dev / tty:
Capturando mensajes de error de libc, redirigiendo desde / dev / tty
Un caso en el que el proceso obtiene SIGABRT de sí mismo: Hrvoje mencionó sobre 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á construida.
#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 SIGABRT realmente se llamó:
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
:)
Como "@sarnold", señaló acertadamente, cualquier proceso puede enviar señal a cualquier otro proceso, por lo tanto, un proceso puede enviar SIGABORT a otro proceso y, en ese caso, el proceso de recepción no puede distinguir si se produce debido a su propio ajuste de memoria, etc., o alguien más tiene "unicastly", envíela.
En uno de los sistemas que trabajé hay un detector de punto muerto que realmente detecta si el proceso está saliendo de alguna tarea al dar latidos cardíacos o no. De lo contrario, declara que el proceso está en estado de punto muerto y le envía SIGABORT.
Solo quería compartir esta perspectiva con referencia a la pregunta formulada.
Daré mi respuesta desde una perspectiva de programación competitiva (cp) , pero también se aplica a otros dominios.
Muchas veces al hacer cp, las restricciones son bastante grandes.
Por ejemplo : tuve una pregunta con variables N, M, Q
como esa 1 ≤ N, M, Q < 10^5
.
El error que estaba cometiendo fue declarar una matriz de tamaño entero 2D 10000 x 10000
en C++
y luché con el SIGABRT
error en Codechef durante casi 2 días.
Ahora, si calculamos:
Tamaño típico de un entero: 4 bytes
No. de celdas en nuestra matriz: 10000 x 10000
Tamaño total (en bytes): 400000000 bytes = 4 * 10 ^ 8 ≈ 400 MB
Sus soluciones a tales preguntas funcionarán en su PC (no siempre) ya que puede permitirse este tamaño.
Pero los recursos en los sitios de codificación (jueces en línea) están limitados a unos pocos KB.
Por lo tanto, el SIGABRT
error y otros errores similares.
Conclusión:
En tales preguntas, no debemos declarar una matriz o vector o cualquier otro DS de este tamaño, pero nuestra tarea es hacer que nuestro algoritmo sea tan eficiente que funcione sin ellos (DS) o con menos memoria.
PD : puede haber otras razones para este error; arriba era uno de ellos.