¿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?
Hay un par de maneras. La forma más fácil, si escribió el programa, es registrar un controlador de señal para SIGABRT que imprima esa información y vacíe sus flujos antes de regresar. La segunda forma más fácil es ejecutar el programa dentro de strace. La tercera forma más fácil es asegurarse de que el programa genere un archivo central cuando se bloquea y averiguarlo a través del volcado del núcleo.
Parthian Shot
Respuestas:
195
abort()envía la SIGABRTseñ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.
para mí, en la mayoría de los casos, SIGABRT fue enviado al libcintentar llamar free()a un puntero no inicializado / dañado
nieto
Si tengo en algún lugar del código, llamada de función virtual pura enterrada desde dentro del constructor, ¿podría eso también terminar con la señal SIGABRT? Pregunto porque veo un error que indica que tengo una llamada virtual pura, y la siguiente línea me da un mensaje SIGABRT y la aplicación se bloquea o el sistema operativo la cierra. Gracias.
Hrvoje
2
En MacOS, obtuvimos SIGABRT por abrir aproximadamente 1000 identificadores de archivos sin cerrarlos. En lugar de burlarse, nuestras pruebas abstrajeron el archivo con un tipo de lector más genérico, que no tiene Close()método, por lo que se olvidó. Aunque tenía una gran cobertura. : rolleyes:
Zyl
52
SIGABRTes 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 assertimplementaciones hacen uso deSIGABRT en caso de una afirmación fallida.
Además, SIGABRTse 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 dashproceso que comencé, por lo que pude encontrar fácilmente el proceso que quería matar.
$ /bin/dash
$ Aborted
La Abortedsalida es al parecer la forma dashreporta 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).
GNU libc imprimirá información /dev/ttysobre 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:
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>usingnamespace std;class A {public:
A(A *pa){pa->f();}virtualvoid f()=0;};class D :public A {public:
D():A(this){}virtualvoid f(){cout<<"D::f\n";}};int main(){
D d;
A *pa =&d;
pa->f();return0;}
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 0x66
rsi 0x69a1690
rdi 0x69a1690
rip 0x7feae3170c37
Código de verificación:
disas 0x7feae3170c37
mov $0xea,%eax =234<-this is the kill syscall, sends signal to process
syscall <-----
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, Qcomo esa 1 ≤ N, M, Q < 10^5.
El error que estaba cometiendo fue declarar una matriz de tamaño entero 2D 10000 x 10000en C++y luché con el SIGABRTerror 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 SIGABRTerror 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.
Respuestas:
abort()
envía laSIGABRT
señal al proceso de llamada , así es comoabort()
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 ejemplomalloc()
, llamaráabort()
si sus estructuras internas están dañadas por un desbordamiento del montón.fuente
libc
intentar llamarfree()
a un puntero no inicializado / dañadoClose()
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.fuente
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.La
Aborted
salida es al parecer la formadash
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 deassert(3)
,abort(3)
oraise(3)
.fuente
Suele ocurrir cuando hay un problema con la asignación de memoria.
Me sucedió cuando mi programa intentaba asignar una matriz con un tamaño negativo.
fuente
Hay otra causa simple en el caso de c ++.
es decir, el alcance del hilo terminó pero olvidó llamar
o
fuente
GNU libc imprimirá información
/dev/tty
sobre algunas condiciones fatales antes de llamarabort()
(que luego se disparaSIGABRT
), 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
fuente
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.
compilar: g ++ -o aa aa.cpp
ulimit -c ilimitado
ejecutar: ./aa
ahora veamos rápidamente el archivo central y validemos que SIGABRT realmente se llamó:
ver reglas:
Código de verificación:
disas 0x7feae3170c37
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
:)
fuente
En mi caso, se debió a una entrada en una matriz en un índice igual a la longitud de la matriz.
Se accede a x [5] que no está presente.
fuente
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.
fuente
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 esa1 ≤ N, M, Q < 10^5
.El error que estaba cometiendo fue declarar una matriz de tamaño entero 2D
10000 x 10000
enC++
y luché con elSIGABRT
error en Codechef durante casi 2 días.Ahora, si calculamos:
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.
fuente