สถานการณ์ใดบ้างที่กระบวนการรับ SIGABRT ใน C ++ สัญญาณนี้มาจากภายในกระบวนการเสมอหรือสามารถส่งสัญญาณนี้จากกระบวนการหนึ่งไปสู่กระบวนการอื่นได้หรือไม่?
มีวิธีการระบุกระบวนการที่กำลังส่งสัญญาณนี้หรือไม่?
สถานการณ์ใดบ้างที่กระบวนการรับ SIGABRT ใน C ++ สัญญาณนี้มาจากภายในกระบวนการเสมอหรือสามารถส่งสัญญาณนี้จากกระบวนการหนึ่งไปสู่กระบวนการอื่นได้หรือไม่?
มีวิธีการระบุกระบวนการที่กำลังส่งสัญญาณนี้หรือไม่?
คำตอบ:
abort()
ส่งสัญญาณการเรียกกระบวนการSIGABRT
นี่คือการabort()
ทำงานโดยทั่วไป
abort()
มักจะถูกเรียกใช้โดยฟังก์ชั่นห้องสมุดซึ่งตรวจจับข้อผิดพลาดภายในหรือข้อ จำกัด บางอย่างที่เสียหายอย่างรุนแรง ตัวอย่างเช่นmalloc()
จะเรียกabort()
ว่าโครงสร้างภายในของมันเสียหายโดยฮีปล้น
libc
พยายามโทรหาพอยน์เตอร์free()
ที่ไม่ได้กำหนดค่าเริ่มต้น / เสียหาย
Close()
วิธีการดังนั้นจึงถูกลืม มีความครอบคลุมที่ดีแม้ว่า : rolleyes:
SIGABRT
โดยทั่วไปจะใช้โดย libc และไลบรารีอื่น ๆ เพื่อยกเลิกโปรแกรมในกรณีที่เกิดข้อผิดพลาดร้ายแรง ตัวอย่างเช่น glibc ส่งSIGABRT
กรณีที่ตรวจพบว่ามีการคอร์รัปชั่นแบบ double-free หรือ heap อื่น ๆ ที่ตรวจพบ
นอกจากนี้assert
การใช้งานส่วนใหญ่ใช้SIGABRT
ในกรณีของการยืนยันที่ล้มเหลว
นอกจากนี้ยังSIGABRT
สามารถส่งจากกระบวนการอื่น ๆ เช่นสัญญาณอื่น ๆ แน่นอนว่ากระบวนการส่งข้อมูลจำเป็นต้องรันด้วยผู้ใช้หรือรูทเดียวกัน
คุณสามารถส่งสัญญาณใด ๆ ไปยังกระบวนการใดก็ได้โดยใช้kill(2)
อินเตอร์เฟส:
kill -SIGABRT 30823
30823 เป็นdash
กระบวนการที่ฉันเริ่มต้นดังนั้นฉันสามารถหากระบวนการที่ฉันต้องการฆ่าได้อย่างง่ายดาย
$ /bin/dash
$ Aborted
Aborted
ผลผลิตเป็นที่เห็นได้ชัดว่าdash
รายงาน SIGABRT
มันสามารถส่งโดยตรงไปยังกระบวนการใด ๆ ที่ใช้kill(2)
หรือกระบวนการที่สามารถส่งสัญญาณไปที่ตัวเองผ่านทางassert(3)
, หรือabort(3)
raise(3)
มันมักจะเกิดขึ้นเมื่อมีปัญหากับการจัดสรรหน่วยความจำ
มันเกิดขึ้นกับฉันเมื่อโปรแกรมของฉันพยายามจัดสรรอาร์เรย์ด้วยขนาดลบ
มีอีกสาเหตุที่ง่ายในกรณีของ c ++
std::thread::~thread{
if((joinable ())
std::terminate ();
}
เช่นขอบเขตของเธรดสิ้นสุดลงแล้ว แต่คุณลืมที่จะโทรเช่นกัน
thread::join();
หรือ
thread::detach();
GNU libc จะพิมพ์ข้อมูล/dev/tty
เกี่ยวกับเงื่อนไขที่ร้ายแรงก่อนที่จะโทรออกabort()
(ซึ่งจะทริกเกอร์SIGABRT
) แต่ถ้าคุณใช้โปรแกรมของคุณเป็นบริการหรือไม่ได้อยู่ในหน้าต่างเทอร์มินัลจริงข้อความเหล่านี้อาจสูญหายเนื่องจากไม่มี tty เพื่อแสดงข้อความ
ดูโพสต์ของฉันในการเปลี่ยนเส้นทาง libc เพื่อเขียนไปยัง stderr แทนที่จะเป็น / dev / tty:
การรับข้อความแสดงข้อผิดพลาด libc เปลี่ยนเส้นทางจาก / dev / tty
กรณีเมื่อกระบวนการได้รับ SIGABRT จากตัวเอง: Hrvoje พูดถึงเกี่ยวกับการถูกเรียกจาก ctor สร้างเสมือนจริงที่ถูกทำแท้งยกเลิกฉันสร้างตัวอย่างสำหรับสิ่งนี้ ที่นี่เมื่อจะสร้าง d มันจะเรียกคลาสพื้นฐานของ ctor และส่งผ่านตัวชี้ภายในไปยังตัวมันเอง ctor เรียกวิธีเสมือนบริสุทธิ์ก่อนตารางเต็มไปด้วยตัวชี้ที่ถูกต้องเพราะ d ยังไม่ได้สร้าง
#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;
}
คอมไพล์: g ++ -o aa aa.cpp
ulimit -c ไม่ จำกัด
run: ./aa
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
ตอนนี้ให้ดูไฟล์หลักได้อย่างรวดเร็วและตรวจสอบว่ามีการเรียก SIGABRT:
gdb aa core
ดู regs:
i r
rdx 0x6 6
rsi 0x69a 1690
rdi 0x69a 1690
rip 0x7feae3170c37
ตรวจสอบรหัส:
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
:)
ในกรณีของฉันมันเป็นเพราะการป้อนข้อมูลในอาร์เรย์ที่ดัชนีเท่ากับความยาวของอาร์เรย์
string x[5];
for(int i=1; i<=5; i++){
cin>>x[i];
}
x [5] กำลังเข้าถึงซึ่งไม่มีอยู่
ในฐานะที่เป็น "@sarnold" ชี้ให้เห็นอย่างเหมาะสมกระบวนการใด ๆ สามารถส่งสัญญาณไปยังกระบวนการอื่น ๆ ดังนั้นกระบวนการหนึ่งสามารถส่ง SIGABORT ไปยังกระบวนการอื่น & ในกรณีนั้นกระบวนการรับไม่สามารถแยกแยะได้ว่ามาจากการปรับแต่งเอง หน่วยความจำ ฯลฯ หรือคนอื่นมี "unicastly" ส่งไป
ในระบบใดระบบหนึ่งที่ฉันทำงานมีตัวตรวจจับการหยุดชะงักหนึ่งตัวที่ตรวจพบว่ากระบวนการออกมาจากงานบางอย่างด้วยการเต้นของหัวใจหรือไม่ หากไม่เป็นเช่นนั้นกระบวนการจะประกาศว่าอยู่ในสถานะหยุดชะงักและส่ง SIGABORT ไปให้
ฉันแค่ต้องการแบ่งปันผู้ที่คาดหวังนี้โดยอ้างอิงจากคำถามที่ถาม
ฉันจะให้คำตอบจากมุมมองการเขียนโปรแกรมการแข่งขัน (cp)แต่มันใช้กับโดเมนอื่นเช่นกัน
หลายครั้งในขณะที่ทำ cp ข้อ จำกัด มีขนาดค่อนข้างใหญ่
ตัวอย่างเช่น : ผมมีคำถามที่มีตัวแปรเป็นเช่นนั้นN, M, Q
1 ≤ N, M, Q < 10^5
ความผิดพลาดที่ผมทำคือผมประกาศให้เป็น 2D จำนวนเต็มอาร์เรย์ของขนาด10000 x 10000
ในC++
และต่อสู้กับSIGABRT
ข้อผิดพลาดที่ Codechef เกือบ 2 วัน
ตอนนี้ถ้าเราคำนวณ:
ขนาดทั่วไปของจำนวนเต็ม: 4 ไบต์
จำนวนเซลล์ในอาร์เรย์ของเรา: 10,000 x 10,000
ขนาดทั้งหมด (เป็นไบต์): 400000000 ไบต์ = 4 * 10 ^ 8 ≈ 400 MB
โซลูชันของคุณสำหรับคำถามดังกล่าวจะทำงานบนพีซีของคุณ (ไม่เสมอไป) เนื่องจากสามารถจ่ายได้ขนาดนี้
แต่ทรัพยากรในเว็บไซต์การเข้ารหัส (ผู้ตัดสินออนไลน์) จำกัด อยู่เพียงไม่กี่ KB
ดังนั้นSIGABRT
ข้อผิดพลาดและข้อผิดพลาดอื่น ๆ
สรุป:
ในคำถามเช่นนี้เราไม่ควรประกาศอาร์เรย์หรือเวกเตอร์หรือ DS อื่น ๆ ที่มีขนาดนี้ แต่หน้าที่ของเราคือการทำให้อัลกอริทึมของเรามีประสิทธิภาพมากขึ้น
PS : อาจมีสาเหตุอื่น ๆ สำหรับข้อผิดพลาดนี้; ด้านบนเป็นหนึ่งในนั้น