Wanneer krijgt een proces SIGABRT (signaal 6)?

Wat zijn de scenario’s waarin een proces een SIGABRT in C++ krijgt? Komt dit signaal altijd van binnen het proces of kan dit signaal van het ene proces naar het andere worden gestuurd?

Is er een manier om te bepalen welk proces dit signaal verzendt?


Antwoord 1, autoriteit 100%

abort()stuurt het aanroepproces het SIGABRTsignaal, dit is hoe abort()in principe werkt.

abort()wordt meestal aangeroepen door bibliotheekfuncties die een interne fout of een ernstig gebroken beperking detecteren. Bijvoorbeeld malloc()roept abort()aan als de interne structuren beschadigd zijn door een heap overflow.


Antwoord 2, autoriteit 25%

SIGABRTwordt vaak gebruikt door libc en andere bibliotheken om het programma af te breken in geval van kritieke fouten. Glibc stuurt bijvoorbeeld een SIGABRTin het geval van een gedetecteerde double-free of andere heapcorrupties.

Bovendien maken de meeste assert-implementaties gebruik van SIGABRTin het geval van een mislukte bevestiging.

Bovendien kan SIGABRTworden verzonden vanuit elk ander proces, net als elk ander signaal. Natuurlijk moet het verzendproces als dezelfde gebruiker of root worden uitgevoerd.


Antwoord 3, autoriteit 22%

Je kunt elk signaal naar elk proces sturen met behulp van de kill(2)-interface:

kill -SIGABRT 30823

30823 was een dash-proces dat ik begon, dus ik kon gemakkelijk het proces vinden dat ik wilde doden.

$ /bin/dash
$ Aborted

De Aborted-uitvoer is blijkbaar hoe dasheen SIGABRT rapporteert.

Het kan rechtstreeks naar elk proces worden gestuurd met behulp van kill(2), of een proces kan het signaal naar zichzelf sturen via assert(3), abort(3), of raise(3).


Antwoord 4, autoriteit 8%

Het gebeurt meestal wanneer er een probleem is met de geheugentoewijzing.

Het overkwam mij toen mijn programma probeerde een
array met negatieve grootte.


Antwoord 5, autoriteit 7%

Er is nog een simpele oorzaak in het geval van c++.

std::thread::~thread{
    if((joinable ())
        std::terminate ();
}

d.w.z. het bereik van de thread is beëindigd, maar je bent een van beide vergeten te bellen

thread::join();

of

thread::detach();

Antwoord 6, autoriteit 3%

De GNU libc zal informatie afdrukken naar /dev/ttymet betrekking tot enkele fatale omstandigheden voordat het abort()aanroept (wat vervolgens SIGABRT), maar als u uw programma als een service uitvoert of anderszins niet in een echt terminalvenster, kunnen deze berichten verloren gaan, omdat er geen tty is om de berichten weer te geven.

Zie mijn bericht over het omleiden van libc om naar stderr te schrijven in plaats van /dev/tty:

Libc-foutmeldingen opvangen, omleiden vanuit /dev/tty


Antwoord 7, autoriteit 2%

Een geval waarin het proces SIGABRT van zichzelf krijgt:
Hrvoje had het over een begraven puur virtueel wezen dat werd aangeroepen door ctor die een abort genereert, ik heb hiervoor een voorbeeld gemaakt.
Hier, wanneer d moet worden geconstrueerd, roept het eerst zijn basisklasse A ctor aan,
en gaat binnen de aanwijzer naar zichzelf.
de acteur roept pure virtuele methode aan voordat de tabel werd gevuld met een geldige aanwijzer,
omdat d nog niet is gebouwd.

#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;
}

compileer: g++ -o aa aa.cpp

ulimit -c onbeperkt

uitvoeren: ./aa

pure virtual method called
terminate called without an active exception
Aborted (core dumped)

Laten we nu snel het kernbestand zien en valideren dat SIGABRT inderdaad heette:

gdb aa core

zie regs:

i r
rdx            0x6      6
rsi            0x69a    1690
rdi            0x69a    1690
rip            0x7feae3170c37

controleer code:

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

🙂


Antwoord 8

In mijn geval was het te wijten aan een invoer in een array met een index die gelijk is aan de lengte van de array.

string x[5];
for(int i=1; i<=5; i++){
    cin>>x[i];
}

x [5] wordt toegankelijk wat niet aanwezig is.


9

Zoals “@sarnold”, opmerkt, kan elk proces signaal naar een ander proces verzenden, vandaar dat één proces sigabort naar andere proces- en versterker kan verzenden; In dat geval kan het ontvangende proces niet onderscheiden of het komt door zijn eigen aanpassing van het geheugen enz., Of iemand anders “unicastly” heeft, ernaar verzenden.

In een van de systemen werkte ik daar een deadlock-detector die daadwerkelijk detecteert of het proces uit een taak komt door hartslag te geven of niet. Zo niet, dan verklaart het het proces in deadlock-toestand en verzendt Sigabort er naar.

Ik wilde dit prospectief gewoon delen met betrekking tot de gevraagde vraag.


Antwoord 10

Met betrekking tot de eerste vraag: What are the scenarios where a process gets a SIGABRT in C++?

Ik kan twee speciale gevallen bedenken waarin een C++-programma automatisch wordt afgebroken — nietdoor rechtstreeks std::abort()of std::terminate():

Eén: gooi een uitzondering terwijl een uitzondering wordt verwerkt.

try {
    throw "abc";
}
catch (...) {
    throw "def";  // abort here
}

Twee: een niet-afgevangen uitzondering die probeert zich buiten main()te verspreiden.

int main(int argc, char** argv)
{
    throw "abc";  // abort here
}

C++-experts zouden waarschijnlijk meer speciale gevallen kunnen noemen.

Er is ook veel goede informatie op deze referentiepagina’s:

Other episodes