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?
Existem algumas maneiras. A maneira mais fácil, se você escreveu o programa, é registrar um manipulador de sinal para o SIGABRT que imprima essas informações e libere seus fluxos antes de retornar. A segunda maneira mais fácil é executar o programa dentro do strace. A terceira maneira mais fácil é garantir que o programa gere um arquivo principal quando ele falhar e descobrir através do dump principal.
Parthian Shot
Respostas:
195
abort()envia o processo de chamada ao SIGABRTsinal, é 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.
para mim, na maioria dos casos, o SIGABRT foi enviado ao libctentar chamar free()um ponteiro não inicializado / corrompido
grandrew
Se eu tiver algum lugar no código, chamada de função virtual pura enterrada de dentro do construtor, isso também pode acabar com o sinal SIGABRT? Estou perguntando quando vejo um erro informando que tenho uma chamada virtual pura, e a próxima linha me dá uma mensagem SIGABRT e o aplicativo trava ou é fechado pelo sistema operacional. Obrigado.
precisa
2
No MacOS, obtivemos o SIGABRT para abrir cerca de 1000 identificadores de arquivos sem fechá-los. Em vez de zombar, nossos testes abstraíram o arquivo com um tipo de leitor mais genérico, que não possui Close()método, por isso foi esquecido. Teve uma grande cobertura embora. : rolleyes:
Zyl
52
SIGABRTé comumente usado pelo libc e outras bibliotecas para abortar o programa em caso de erros críticos. Por exemplo, o glibc envia um SIGABRTno caso de uma corrupção de heap dupla detectada ou outras detectadas.
Além disso, a maioria das assertimplementações é utilizada SIGABRTem caso de falha na declaração.
Além disso, SIGABRTpode 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.
O GNU libc imprimirá as informações /dev/ttyreferentes 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:
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>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 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 0x66
rsi 0x69a1690
rdi 0x69a1690
rip 0x7feae3170c37
verifique o código:
disas 0x7feae3170c37
mov $0xea,%eax =234<-this is the kill syscall, sends signal to process
syscall <-----
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, Qcomo essa 1 ≤ N, M, Q < 10^5.
O erro que eu estava fazendo era eu declarei um 2D inteiro matriz de tamanho 10000 x 10000em C++e lutou com o SIGABRTerro 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 SIGABRTerro 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.
Respostas:
abort()
envia o processo de chamada aoSIGABRT
sinal, é assim queabort()
basicamente funciona.abort()
é geralmente chamado por funções de biblioteca que detectam um erro interno ou alguma restrição seriamente quebrada. Por exemplomalloc()
, chamaráabort()
se suas estruturas internas forem danificadas por um estouro de heap.fonte
libc
tentar chamarfree()
um ponteiro não inicializado / corrompidoClose()
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 umSIGABRT
no caso de uma corrupção de heap dupla detectada ou outras detectadas.Além disso, a maioria das
assert
implementações é utilizadaSIGABRT
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.fonte
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.A
Aborted
saída é, aparentemente, comodash
relata um SIGABRT.Ele pode ser enviado diretamente para qualquer processo usando
kill(2)
, ou um processo pode enviar o sinal para si viaassert(3)
,abort(3)
ouraise(3)
.fonte
Geralmente acontece quando há um problema com a alocação de memória.
Aconteceu comigo quando meu programa estava tentando alocar uma matriz com tamanho negativo.
fonte
Há outra causa simples no caso de c ++.
ou seja, o escopo do segmento terminou, mas você esqueceu de chamar
ou
fonte
O GNU libc imprimirá as informações
/dev/tty
referentes a algumas condições fatais antes de serem chamadasabort()
(o que é acionadoSIGABRT
), 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
fonte
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.
compilar: g ++ -o aa aa.cpp
ulimit -c unlimited
executar: ./aa
agora vamos ver rapidamente o arquivo principal e validar que SIGABRT foi realmente chamado:
veja regs:
verifique o código:
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
:)
fonte
No meu caso, isso ocorreu devido a uma entrada em uma matriz com um índice igual ao comprimento da matriz.
x [5] está sendo acessado que não está presente.
fonte
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.
fonte
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 essa1 ≤ N, M, Q < 10^5
.O erro que eu estava fazendo era eu declarei um 2D inteiro matriz de tamanho
10000 x 10000
emC++
e lutou com oSIGABRT
erro na Codechef por quase 2 dias.Agora, se calcularmos:
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.
fonte