Quais são os cenários em que um processo obtém um SIGABRT em C ++? Esse sinal sempre vem de dentro do processo ou pode ser enviado de um processo para outro?
Existe uma maneira de identificar qual processo está enviando esse sinal?
Quais são os cenários em que um processo obtém um SIGABRT em C ++? Esse sinal sempre vem de dentro do processo ou pode ser enviado de um processo para outro?
Existe uma maneira de identificar qual processo está enviando esse sinal?
Respostas:
abort()
envia o processo de chamada ao SIGABRT
sinal, é assim que abort()
basicamente funciona.
abort()
é geralmente chamado por funções de biblioteca que detectam um erro interno ou alguma restrição seriamente quebrada. Por exemplo malloc()
, chamará abort()
se suas estruturas internas forem danificadas por um estouro de heap.
libc
tentar chamar free()
um ponteiro não inicializado / corrompido
Close()
método, por isso foi esquecido. Teve uma grande cobertura embora. : rolleyes:
SIGABRT
é comumente usado pelo libc e outras bibliotecas para abortar o programa em caso de erros críticos. Por exemplo, o glibc envia um SIGABRT
no caso de uma corrupção de heap dupla detectada ou outras detectadas.
Além disso, a maioria das assert
implementações é utilizada SIGABRT
em caso de falha na declaração.
Além disso, SIGABRT
pode ser enviado de qualquer outro processo, como qualquer outro sinal. Obviamente, o processo de envio precisa ser executado como o mesmo usuário ou raiz.
Você pode enviar qualquer sinal para qualquer processo usando a kill(2)
interface:
kill -SIGABRT 30823
O 30823 foi um dash
processo que eu iniciei, para que eu pudesse encontrar facilmente o processo que queria matar.
$ /bin/dash
$ Aborted
A Aborted
saída é, aparentemente, como dash
relata um SIGABRT.
Ele pode ser enviado diretamente para qualquer processo usando kill(2)
, ou um processo pode enviar o sinal para si via assert(3)
, abort(3)
ou raise(3)
.
Há outra causa simples no caso de c ++.
std::thread::~thread{
if((joinable ())
std::terminate ();
}
ou seja, o escopo do segmento terminou, mas você esqueceu de chamar
thread::join();
ou
thread::detach();
O GNU libc imprimirá as informações /dev/tty
referentes a algumas condições fatais antes de serem chamadas abort()
(o que é acionado SIGABRT
), mas se você estiver executando o programa como um serviço ou não em uma janela real do terminal, essas mensagens poderão se perder, porque não há tty para exibir as mensagens.
Veja meu post sobre o redirecionamento da libc para gravar no stderr em vez de / dev / tty:
Captura de mensagens de erro da libc, redirecionando de / dev / tty
Um caso em que o processo obtém o SIGABRT: Hrvoje mencionado sobre um virtual virtual puro chamado de ctor gerando um aborto, recriei um exemplo para isso. Aqui, quando d deve ser construído, ele primeiro chama seu classe de classe Ator e passa o ponteiro para si mesmo. o Ator chama o método virtual puro antes de a tabela ser preenchida com um ponteiro válido, porque d ainda não foi construído.
#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 unlimited
executar: ./aa
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
agora vamos ver rapidamente o arquivo principal e validar que SIGABRT foi realmente chamado:
gdb aa core
veja regs:
i r
rdx 0x6 6
rsi 0x69a 1690
rdi 0x69a 1690
rip 0x7feae3170c37
verifique o código:
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", apropriadamente apontado, qualquer processo pode enviar sinal para qualquer outro processo, portanto, um processo pode enviar SIGABORT para outro processo e, nesse caso, o processo de recebimento é incapaz de distinguir se está ocorrendo devido a seus próprios ajustes de memória etc, ou alguém tiver "unicastly", envie para ele.
Em um dos sistemas que trabalhei, há um detector de impasse que realmente detecta se o processo está saindo de alguma tarefa dando batimentos cardíacos ou não. Caso contrário, ele declara que o processo está no estado de deadlock e envia SIGABORT para ele.
Eu só queria compartilhar esse potencial com referência à pergunta feita.
Darei minha resposta de uma perspectiva de programação competitiva (cp) , mas ela também se aplica a outros domínios.
Muitas vezes ao fazer cp, as restrições são bastante grandes.
Por exemplo : eu tive uma pergunta com variáveis N, M, Q
como essa 1 ≤ N, M, Q < 10^5
.
O erro que eu estava fazendo era eu declarei um 2D inteiro matriz de tamanho 10000 x 10000
em C++
e lutou com o SIGABRT
erro na Codechef por quase 2 dias.
Agora, se calcularmos:
Tamanho típico de um número inteiro: 4 bytes
Nº de células em nossa matriz: 10000 x 10000
Tamanho total (em bytes): 400000000 bytes = 4 * 10 ^ 8 ~ 400 MB
Suas soluções para essas perguntas funcionarão no seu PC (nem sempre), pois podem suportar esse tamanho.
Mas os recursos nos sites de codificação (juízes on-line) são limitados a poucos KBs.
Portanto, o SIGABRT
erro e outros erros desse tipo.
Conclusão:
Em tais perguntas, não devemos declarar uma matriz ou vetor ou qualquer outro DS desse tamanho, mas nossa tarefa é tornar nosso algoritmo tão eficiente que funcione sem eles (DS) ou com menos memória.
PS : Pode haver outros motivos para esse erro; acima foi um deles.