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 SIGABRT
signaal, 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%
SIGABRT
wordt vaak gebruikt door libc en andere bibliotheken om het programma af te breken in geval van kritieke fouten. Glibc stuurt bijvoorbeeld een SIGABRT
in het geval van een gedetecteerde double-free of andere heapcorrupties.
Bovendien maken de meeste assert
-implementaties gebruik van SIGABRT
in het geval van een mislukte bevestiging.
Bovendien kan SIGABRT
worden 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 dash
een 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/tty
met 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: