2010-08-05 14 views
133

ऐसे परिदृश्य क्या हैं जहां प्रक्रिया को C++ में SIGABRT मिलता है? क्या यह संकेत हमेशा प्रक्रिया के भीतर से आता है या क्या यह सिग्नल एक प्रक्रिया से दूसरे प्रक्रिया में भेजा जा सकता है?प्रक्रिया को SIGABRT (सिग्नल 6) कब मिलता है?

वहाँ जो प्रक्रिया इस संकेत भेज रहा है पहचान करने के लिए एक तरीका है?

+2

कुछ तरीके हैं। सबसे आसान तरीका, यदि आपने प्रोग्राम लिखा है, तो सिगैबर्ट के लिए सिग्नल हैंडलर पंजीकृत करना है जो उस जानकारी को प्रिंट करता है और लौटने से पहले अपनी धाराओं को फ्लश करता है। कार्यक्रम को चलाने के लिए दूसरा सबसे आसान तरीका है। तीसरा सबसे आसान तरीका यह सुनिश्चित करना है कि कार्यक्रम क्रैश होने पर कोर फ़ाइल उत्पन्न करता है, और कोर डंप के माध्यम से पता लगाता है। अधिकांश मामलों में –

उत्तर

134

abort() कॉलिंग प्रक्रिया SIGABRT सिग्नल भेजता है, इस प्रकार abort() मूल रूप से काम करता है।

abort() आमतौर पर जो एक आंतरिक त्रुटि या कुछ गंभीरता से टूट बाधा का पता लगाने के पुस्तकालय कार्यों द्वारा कहा जाता है। उदाहरण malloc() लिए abort() फोन की आंतरिक संरचना एक ढेर अतिप्रवाह से क्षतिग्रस्त हो रहे हैं होगा।

+14

मेरे लिए SIGABRT को 'libc'' द्वारा गैर-प्रारंभिक/दूषित पॉइंटर – grandrew

+0

पर 'फ्री()' कॉल करने का प्रयास करके भेजा गया था यदि मेरे पास कोड में कहीं है, तो कन्स्ट्रक्टर के भीतर से शुद्ध वर्चुअल फ़ंक्शन कॉल को दफन कर दिया गया है, एसआईजीएबीआरटी सिग्नल के साथ भी खत्म हो गया? मैं पूछ रहा हूं क्योंकि मुझे एक त्रुटि दिखाई दे रही है जिसमें कहा गया है कि मेरे पास शुद्ध वर्चुअल कॉल है, और अगली पंक्ति मुझे एक SIGABRT संदेश देती है और एप्लिकेशन या तो क्रैश या ऑपरेटिंग सिस्टम द्वारा बंद हो जाता है। धन्यवाद। – Hrvoje

44

आप kill(2) इंटरफ़ेस का उपयोग कर किसी भी प्रक्रिया के लिए किसी भी संकेत भेज सकते हैं:

kill -SIGABRT 30823

30823 एक dash प्रक्रिया मैंने शुरू किया था, तो मैं आसानी से प्रक्रिया मैं मारना चाहते थे मिल सकता है।

$ /bin/dash 
$ Aborted 

Aborted उत्पादन जाहिरा तौर पर कैसे dash एक SIGABRT रिपोर्ट है।

यह kill(2) उपयोग कर किसी भी प्रक्रिया के लिए सीधे भेजा जा सकता है, या एक प्रक्रिया assert(3), abort(3), या raise(3) के माध्यम से ही करने के लिए संकेत भेज सकते हैं।

37

SIGABRT सामान्यतः libc और अन्य पुस्तकालयों द्वारा प्रयोग किया जाता है गंभीर त्रुटियों के मामले में progamm निरस्त करने के लिए। उदाहरण के लिए, ग्लिबैक एक डबल 12 मुक्त या अन्य ढेर भ्रष्टाचार के मामले में SIGABRT भेजता है।

इसके अलावा, अधिकांश "assert" कार्यान्वयन विफल असर के मामले में SIGABRT का उपयोग करते हैं।

इसके अलावा, SIGABRT किसी अन्य संकेत की तरह किसी अन्य प्रक्रिया से भेजने जा सकता है। बेशक, भेजने की प्रक्रिया को उसी उपयोगकर्ता या रूट के रूप में चलाने की आवश्यकता है।

12

यह आमतौर पर तब होता है जब स्मृति आवंटन के साथ एक समस्या हो।

यह तब हुआ जब मेरा प्रोग्राम नकारात्मक आकार के साथ सरणी आवंटित करने का प्रयास कर रहा था।

3

जीएनयू libc बाहर जानकारी /dev/tty करने के लिए कुछ घातक स्थिति के बारे में प्रिंट होगा इससे पहले कि यह abort() कॉल (जो तब SIGABRT से चलाता है), लेकिन आप एक असली टर्मिनल विंडो में नहीं एक सेवा के रूप में अपने कार्यक्रम चलाने या अन्यथा कर रहे हैं, ये संदेश कर सकते हैं खो जाओ, क्योंकि संदेशों को प्रदर्शित करने के लिए कोई tty नहीं है।

के बजाय/dev/tty stderr करने के लिए लिखने के लिए libc पुनः निर्देशित पर मेरी पोस्ट देखें:

Catching libc error messages, redirecting from /dev/tty

6

ग के मामले में एक और सरल कारण है ++।

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

यानी।धागे की गुंजाइश समाप्त हो गया है, लेकिन आप कॉल करने के लिए भूल गया या तो

thread::join(); 

या

thread::detach(); 
1

मेरे मामले में, यह एक सूचकांक सरणी की लंबाई के बराबर में एक सरणी में एक इनपुट के कारण था।

string x[5]; 

for(int i=1; i<=5; i++){ 

    cin>>x[i]; 

} 

[5] एक्स पहुँचा जा रही है जो मौजूद नहीं है।

2

एक मामला है जब प्रक्रिया से ही SIGABRT मिलती है: हर्वोजे एक दफन शुद्ध आभासी किया जा रहा है एक बीच में बंद करें पैदा ctor से कहा जाता है के बारे में उल्लेख किया है, मैं इस के लिए एक उदाहरण निर्मित। यहां जब डी का निर्माण किया जाना है, तो पहले यह अपनी बेस क्लास ए सीटीओआर, कहता है और पॉइंटर के अंदर ही पास हो जाता है। एक सीटीओआर शुद्ध पॉइंटर, से भरने से पहले शुद्ध वर्चुअल विधि को कॉल करता है क्योंकि डी अभी तक नहीं बनाया गया है।

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

संकलन: जी ++ -ओ आ aa.cpp

ulimit -c असीमित

रन: ./aa

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

अब जल्दी से कोर फ़ाइल देखते हैं, और मान्य की सुविधा देता है कि SIGABRT को वास्तव में बुलाया गया था:

gdb aa core 

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

चेक कोड::

regs देख

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 पीआईडी ​​पूर्णांक sig = 6 = SIGABRT

:)

संबंधित मुद्दे