2013-05-01 4 views
25

जीडीबी एक को फेंकने पर अपवाद पकड़ने की अनुमति देता है, और जब वे पकड़े जाते हैं। लेकिन कभी-कभी लाइन को अपवाद को फेंकने के लिए कोई प्रतीक नहीं होता है, या अपवाद हैंडलिंग के दौरान ब्रेकपॉइंट ट्रिगर होता है। मैं वर्तमान अपवाद के मूल्य का निरीक्षण कैसे करूं?मैं gdb का उपयोग कर C++ में वर्तमान अपवाद का मान और प्रकार कैसे प्राप्त करूं?

उत्तर

8

अपडेट किया गया


यहाँ GDB से कुछ जानकारी मैनुअल है

वर्तमान सेल्सियस तक ++ अपवाद कुछ सीमाएं gdb में से निपटने (पकड़ फेंक और पकड़ पकड़) के होते हैं:

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

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

 /* addr is where the exception identifier is stored. 
     id is the exception identifier. */ 
    void __raise_exception (void **addr, void *id); To make the debugger catch all exceptions before any stack unwinding takes place, 

__raise_exception पर एक ब्रेकपाइंट सेट (; watchpoints; ब्रेकप्वाइंट देख और अपवाद)।


कहा कि

यह कोड पर निर्भर करता है और आप ढेर में हैं जहां। आप वास्तव में के रूप में अपवाद पकड़ा हैं:

try { .... } catch (std::exception &e) { 
    //do stuff 
} 

आप शायद मुद्रण e.what() प्रयास करें, या अपवाद के सदस्यों को देखने के कर सकते हैं। यदि आपने इसे अभी (...) के रूप में पकड़ा है तो मुझे यकीन नहीं है कि आप क्या इकट्ठा करने में सक्षम होंगे।

एक और हैंडलिंग चीज जो आप कर सकते हैं वह है जीडीबी में 'फेंक' पकड़ना और पकड़ना 'पकड़ो' साथ ही यदि आप वास्तव में पूरे प्रवाह का पालन करना चाहते हैं।

gdb> catch catch 
gdb> catch throw 

इस तरह आप एक breakpoints मिल जाएगा ठीक पहले अपवाद फेंक दिया जाता है और सही रूप में वे पकड़े जाते हैं, तो आप ढेर चलना क्या हो रहा था के बारे में अधिक जानकारी हासिल करने के लिए कर सकता है। यहां तक ​​कि यदि आप एक और ब्रेक पॉइंट में हैं, तो आप उस फ्रेम को प्राप्त करने के लिए स्टैक (ऊपर या नीचे का उपयोग करके) चलने में सक्षम होना चाहिए जिसमें अपवाद दिखाई दे रहा है।

3

संक्षिप्त उत्तर: आप ऐसा नहीं कर सकते क्योंकि अपवाद हैंडलिंग का अधिकांश काम आपके प्रोग्राम के बाहर किया जाता है, और इसलिए जीडीबी के दायरे से बाहर है।

जवाब की व्याख्या:

कभी कभी लाइन एक अपवाद फेंक दिया जाता है कोई प्रतीकों

द्विआधारी आप डिबगिंग रहे हैं कोई डिबग प्रतीकों तो द्विआधारी शायद छीन गया, तो है और आप जीता ' किसी भी चीज़ के प्रकार/मूल्यों के बारे में बिल्कुल कुछ नहीं ढूंढ पाएंगे।

मैं वर्तमान अपवाद के मूल्य का निरीक्षण कैसे करूं?

मुझे लगता है कि आप यहां मान रहे हैं कि अपवाद एक भाषा सुविधा है जिसे जीडीबी निरीक्षण कर सकता है; वास्तव में सी ++ में एक अपवाद सी ++ से लैबैक ++ और एबीआई की भाषा के रूप में सुविधाओं का संयोजन है। और यहां तक ​​कि एक सक्रिय सक्रिय अपवाद भी हो सकता है।

ऊपर की तरह एंडएडम बताता है कि आप एक प्रकार के विनिर्देशक के साथ एक कैच ब्लॉक में ब्रेकपॉइंट सेट कर सकते हैं, और उसके बाद उस तत्व का निरीक्षण कर सकते हैं, लेकिन मुझे संदेह है कि आपकी समस्या उन मामलों में है जहां आपको "पकड़ (...)" मिलता है। उन मामलों में आप वर्तमान अपवाद के बारे में ज्यादा कुछ नहीं सीख पाएंगे जबतक कि आप अपवाद हैंडलिंग के कार्यान्वयन में खुदाई नहीं करते।

एक बहुत ही कम और अधूरा विवरण हम कह सकते हैं कि एक अपवाद फेंक के साथ

:

  1. आपका कार्यक्रम libC++ फोन करेगा एक अपवाद
  2. बढ़ाने के लिए libC++ फोन करेगा glibc में "तनाव कम" ढेर शुरू करने के लिए अवांछित
  3. अनचाहे प्रत्येक स्टैक फ्रेम (मूल रूप से स्टैक में प्रत्येक फ़ंक्शन कॉल) के लिए libC++ से "व्यक्तित्व फ़ंक्शन" को कॉल करेगा,
  4. व्यक्तित्व फ़ंक्शन किसी भी तरह से तय करेगा कि वर्तमान स्टैक फ्रेम इसे संभाल सकता है या नहीं अपवाद
  5. यदि अपवाद संभाला जा सकता है कैच ब्लॉक

निष्पादित किया जाएगा अब, यह विवरण के बारे में बात करने के लिए मुश्किल है क्योंकि अपवाद संचालन का एक बहुत अपने toolchain पर निर्भर करता है (संकलक, मंच, वास्तुकला, libC++, आदि) लेकिन ज्यादातर मामलों में "पकड़ (...)" को तर्क के रूप में मूल अपवाद भी प्राप्त नहीं होगा। किसी भी मामले में, किसी भी तरह अपने सवाल का जवाब देने: gnu के libc साथ जीसीसी में ++ आप कुछ इस तरह की कोशिश कर सकते:

  1. डिबगिंग प्रतीकों
  2. __gxx_personality_v0 में एक ब्रेकपाइंट सेट के साथ एक libC++ (कि व्यक्तित्व समारोह कहा जाता है) प्राप्त करें।इस फ़ंक्शन को यह निर्धारित करने के लिए बुलाया जाएगा कि क्या एक स्टैक फ्रेम (फ़ंक्शन कॉल, मूल रूप से) अपवाद को संभालने के लिए एक उपयुक्त कैच ब्लॉक है
  3. व्यक्तित्व फ़ंक्शन में आप _Unwind_Exception को एक पॉइंटर ढूंढ पाएंगे, जो एक रैपर है आपके वास्तविक अपवाद
  4. इस तरह के अपवाद के लिए टाइप जानकारी प्राप्त करें: __cxa_exception * upgrade_header = (__cxa_exception *) (unwind_exception + 1) -1; std :: type_info * thrown_exception_type = upgrade_header-> अपवाद टाइप;
  5. आप एक अपवाद प्रकार है जो आप तो RTTI के बाकी अपने कोड

के लिए परिभाषित किसी भी मामले में साथ देखने कर सकते हैं मिल जाएगा, तो आप शायद समझने की कोशिश कर समय की काफ़ी खर्च करने की आवश्यकता होगी आपके प्लेटफार्म में अपवाद हैंडलिंग कैसे लागू की जाती है। यदि आप अपवाद हैंडलिंग के बारे में कुछ और पढ़ना चाहते हैं, तो मैंने पिछले लेख में @http://monoinfinito.wordpress.com/series/exception-handling-in-c/ विषय के बारे में कुछ समय बिताया था। यह एक आधिकारिक स्रोत नहीं है लेकिन इसमें अपवाद को संभालने में शामिल प्रत्येक भाग की चश्मे के लिंक हैं।

3

ये उत्तर सही होने पर सही थे, लेकिन तब से gdb और libstdC++ बदल गए हैं।

libstdC++ में अब कुछ हुक हैं जो जीडीबी अपवाद प्रणाली के साथ अधिक अच्छी तरह से बातचीत करते हैं। विशेष रूप से, अब उपयोगकर्ता को $_exception सुविधा चर प्रदान करने के लिए जीडीबी के लिए पर्याप्त जानकारी सामने आई है। इस चर को अपवाद को फेंक दिया गया है। यह केवल उस स्थान पर मान्य है जहां अपवाद पकड़ा जा रहा है; जिसे आप catch catch का उपयोग कर रोक सकते हैं।

विवरण के लिए the page from the manual देखें।

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