एक अपवाद होने तक GDB में एक अनुप्रयोग चलाएँ


102

मैं एक multithreaded एप्लिकेशन पर काम कर रहा हूं, और मैं इसे GDB का उपयोग करके डीबग करना चाहता हूं।

समस्या यह है कि, मेरा एक सूत्र संदेश के साथ मरता रहता है:

pure virtual method called
terminate called without an active exception
Abort

मुझे उस संदेश का कारण पता है, लेकिन मुझे नहीं पता कि मेरे धागे में यह कहां होता है। एक backtrace वास्तव में उपयोगी होगा।

जब मैं अपना ऐप GDB में चलाता हूं, तो यह हर बार थ्रेड निलंबित या फिर से शुरू होने पर रुक जाता है। मैं चाहता हूं कि मेरा ऐप सामान्य रूप से चलता रहे, जब तक कि थ्रेड्स में से कोई भी उस अपवाद के साथ मर न जाए, जिस बिंदु पर सब कुछ रुक जाना चाहिए ताकि मुझे बैकट्रेस मिल सके।


जब यह रुकता है तो GDB की क्या संकेत मिलता है? आप की तरह एक आदेश को चलाने के लिए सक्षम होना चाहिएhandle SIGUSR1 pass noprint nostop
Hasturkun

जवाबों:


147

आप एक "कैचपॉइंट" ( catch throw) का उपयोग करके उस बिंदु पर डिबगर को रोकने का प्रयास कर सकते हैं जहां अपवाद उत्पन्न होता है।

निम्नलिखित अंश gdb मैनुअल से कैचपॉइंट सुविधा का वर्णन करता है।


5.1.3 कैचपॉइंट सेट करना

आप डिबगर का उपयोग करने के लिए डिबगर के कारण कुछ प्रकार की प्रोग्राम ईवेंट्स, जैसे C ++ अपवाद या साझा लायब्रेरी को लोड करने के लिए रोक सकते हैं। कैचपॉइंट सेट करने के लिए कैच कमांड का उपयोग करें।

  • घटना को पकड़ने

    घटना होने पर रुकें । घटना निम्न में से कोई भी हो सकती है:

    • फेंकना

      C ++ अपवाद का फेंकना।

    • पकड़

      C ++ अपवाद को पकड़ना।

    • कार्यकारी

      निष्पादन के लिए एक कॉल। यह वर्तमान में केवल HP-UX के लिए उपलब्ध है।

    • कांटा

      कांटा लगाने का बुलावा। यह वर्तमान में केवल HP-UX के लिए उपलब्ध है।

    • vfork

      Vfork के लिए एक कॉल। यह वर्तमान में केवल HP-UX के लिए उपलब्ध है।

    • libname लोड या लोड करें

      किसी भी साझा पुस्तकालय के गतिशील लोडिंग, या पुस्तकालय libname के लोडिंग। यह वर्तमान में केवल HP-UX के लिए उपलब्ध है।

    • उतारना या उतारना libname

      किसी भी गतिशील रूप से भरी हुई साझा लायब्रेरी को उतारना, या लायब्रेरी के काम का बोझ उतारना। यह वर्तमान में केवल HP-UX के लिए उपलब्ध है।

  • tcatch घटना

    कैचपॉइंट सेट करें जो केवल एक स्टॉप के लिए सक्षम है। पहली बार इवेंट पकड़े जाने के बाद कैचपॉइंट अपने आप डिलीट हो जाता है।

info breakवर्तमान कैचपॉइंट्स को सूचीबद्ध करने के लिए कमांड का उपयोग करें ।

वर्तमान में GDB में C ++ अपवाद हैंडलिंग (कैच थ्रो और कैच पकड़ने) की कुछ सीमाएँ हैं:

  • यदि आप किसी फ़ंक्शन को अंतःक्रियात्मक रूप से कॉल करते हैं, तो फ़ंक्शन को निष्पादित करने के बाद GDB सामान्य रूप से आपका नियंत्रण लौटाता है। यदि कॉल अपवाद को उठाता है, तो, कॉल उस तंत्र को बायपास कर सकता है जो आपके नियंत्रण को वापस लौटाता है और आपके प्रोग्राम को या तो गर्भपात का कारण बनता है या बस तब तक चलता रहता है जब तक कि यह एक ब्रेकपॉइंट को हिट नहीं करता है, एक संकेत को पकड़ता है जो GDB के लिए सुन रहा है, या बाहर निकलता है। यदि आप अपवाद के लिए कैचपॉइंट सेट करते हैं तो भी यही स्थिति है; अपवादों पर कैच पॉइंट्स इंटरेक्टिव कॉल के भीतर अक्षम हैं।

  • आप एक अपवाद को अंतःक्रियात्मक रूप से नहीं उठा सकते।

  • आप एक अपवाद हैंडलर को संवादात्मक रूप से स्थापित नहीं कर सकते।

कभी-कभी अपवाद अपवाद हैंडलिंग डीबग करने का सबसे अच्छा तरीका नहीं है: यदि आपको यह जानना आवश्यक है कि अपवाद कहां से उठाया गया है, तो अपवाद हैंडलर को कॉल करने से पहले रोकना बेहतर होता है, क्योंकि इस तरह से आप किसी भी अनहोनी से पहले स्टैक देख सकते हैं। यदि आप इसके बजाय एक अपवाद हैंडलर में एक ब्रेकपॉइंट सेट करते हैं, तो यह पता लगाना आसान नहीं होगा कि अपवाद कहां उठाया गया था।

अपवाद हैंडलर को बुलाए जाने से ठीक पहले रोकने के लिए, आपको कार्यान्वयन के कुछ ज्ञान की आवश्यकता है। GNU C ++ के मामले में, अपवादों को __raise_exception नामक एक लाइब्रेरी फ़ंक्शन को कॉल करके उठाया जाता है, जिसमें निम्नलिखित ANSI C इंटरफ़ेस है:

/* addr is where the exception identifier is stored.
   id is the exception identifier.  */
void __raise_exception (void **addr, void *id);

डीबगर को किसी भी स्टैक अनइंडिंग होने से पहले सभी अपवादों को पकड़ने के लिए, __raise_exception (अनुभाग ब्रेकपॉइंट; वॉचपॉइंट; और अपवाद देखें) पर एक ब्रेकप्वाइंट सेट करें।

सशर्त ब्रेकपॉइंट (अनुभाग तोड़ स्थितियां देखें) के साथ, जो आईडी के मूल्य पर निर्भर करता है, आप एक विशिष्ट अपवाद उठाए जाने पर अपने कार्यक्रम को रोक सकते हैं। जब कई अपवादों को उठाया जाता है, तो आप अपने प्रोग्राम को रोकने के लिए कई सशर्त ब्रेकप्वाइंट का उपयोग कर सकते हैं।


आप अपवाद के प्रकार को पकड़ने के लिए भी निर्दिष्ट कर सकते हैं, जैसे catch throw std::runtime_exception
स्काइ

5

__Pure_virtual पर एक ब्रेकपॉइंट सेट करें


@ जेफ्रीहिल जवाब में, इसे __cxa_pure_virtual कहा जाता है। मुझे नहीं पता कि मुझे कैसे जांचना है, इसलिए मैं उत्तर को संपादित नहीं करना चाहता। मैं डाउन-वोट करने का इरादा नहीं रखता, लेकिन जवाब अब गलत हो सकता है और किसी ऐसे व्यक्ति द्वारा संपादित किया जाना चाहिए जो जानता है कि क्या सही है।
फिलिप क्लेन

5

FWIW, जाहिरा तौर पर, gcc 4.1 में, उपयुक्त फ़ंक्शन नाम बदल गया है और किसी को इस फ़ंक्शन में एक ब्रेकपॉइंट सेट करना होगा।

__cxa_pure_virtual


0

केवल नीचे मेरे लिए gdb 8.3 के साथ काम किया:

break _Unwind_RaiseException

"कैच थ्रो" या "ब्रेक __cxx_throw" मेरे लिए काम नहीं किया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.