ठीक है, तो कल्पना कीजिए कि मेरा ब्रेकपाइंट objc_exception_throw
अभी शुरू हुआ है। मैं डिबगर प्रॉम्प्ट पर बैठा हूं, और मैं अपवाद ऑब्जेक्ट के बारे में कुछ और जानकारी प्राप्त करना चाहता हूं। मैं उसे कहाँ ढूँढू?
ठीक है, तो कल्पना कीजिए कि मेरा ब्रेकपाइंट objc_exception_throw
अभी शुरू हुआ है। मैं डिबगर प्रॉम्प्ट पर बैठा हूं, और मैं अपवाद ऑब्जेक्ट के बारे में कुछ और जानकारी प्राप्त करना चाहता हूं। मैं उसे कहाँ ढूँढू?
जवाबों:
अपवाद ऑब्जेक्ट को पहले तर्क के रूप में पास किया जाता है objc_exception_throw
। LLDB प्रदान करता है $arg1
.. $argn
सही कॉलिंग कन्वेंशन में तर्कों को संदर्भित करने के लिए चर, अपवाद विवरण प्रिंट करना सरल बनाता है:
(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]
objc_exception_throw
इन आदेशों को निष्पादित करने से पहले कॉल स्टैक में फ़्रेम का चयन करना सुनिश्चित करें । WWDC15 सत्र के वीडियो में "उन्नत डिबगिंग और एड्रेस सैनिटाइज़र" देखें, इसे मंच पर प्रदर्शित किया जाए।
आउटडेटेड जानकारी
यदि आप GDB पर हैं, तो पहले तर्क को संदर्भित करने वाला सिंटैक्स आपके द्वारा चलाए जा रहे आर्किटेक्चर के कॉलिंग सम्मेलनों पर निर्भर करता है। यदि आप वास्तविक iOS डिवाइस पर डिबगिंग कर रहे हैं, तो ऑब्जेक्ट का पॉइंटर रजिस्टर में है r0
। इसे मुद्रित करने या इसे संदेश भेजने के लिए, निम्नलिखित सरल वाक्यविन्यास का उपयोग करें:
(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]
IPhone सिम्युलेटर पर, सभी फ़ंक्शन तर्क स्टैक पर पारित किए जाते हैं, इसलिए वाक्यविन्यास काफी भयानक है। सबसे छोटी अभिव्यक्ति जो मैं बना सकता था, वह है *(id *)($ebp + 8)
। चीजों को कम दर्दनाक बनाने के लिए, मैं एक सुविधा चर का उपयोग करने का सुझाव देता हूं:
(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]
$exception
जब भी ब्रेकपॉइंट पर कमांड की सूची जोड़कर ब्रेकपाइंट को ट्रिगर किया जाता है, तो आप स्वचालित रूप से सेट कर सकते हैं objc_exception_throw
।
(ध्यान दें कि मैंने जितने भी मामलों में परीक्षण किया था , ब्रेकप्वाइंट के हिट होने के समय अपवाद ऑब्जेक्ट भी मौजूद था eax
और edx
पंजीकृत करता है। मुझे यकीन नहीं है कि मैं हमेशा मामला बना रहूंगा, हालांकि।)
नीचे टिप्पणी से जोड़ा गया:
Lldb में , इसके लिए स्टैक फ्रेम का चयन करें objc_exception_throw
और फिर इस कमांड को दर्ज करें:
(lldb) po *(id *)($esp + 4)
objc_exception_throw
में LLDB : po *(id *)($esp + 4)
।
objc_exception_throw
)।
po $eax
$r0
डिवाइस पर कब तक लटकन के रूप में सिम्युलेटर में मेरे लिए काम करता है।
नए सिमुलेटर पर (iOS 8, 64 बिट) एक्सकोड 6 इम अपवाद फ्रेम में उपयोग कर रहा है: objc_exception_throw
po $rax
32 बिट में:
po $eax
रक्स क्या है?
रैक्स 64 बिट्स रजिस्टर है जो पुराने ईएक्सएक्स की जगह लेता है
सभी रजिस्टरों को कैसे खोजें?
register read
इस लेखन के समय, यह पोस्ट मेरे लिए शीर्ष Google हिट है: lldb प्रिंट अपवाद । इस प्रकार, मैं इस उत्तर को lldb और x86_64 के लिए जोड़ रहा हूं।
के po $eax
साथ असफल का उपयोग कर अपवाद को खोजने के लिए मेरे प्रयास error: Couldn't materialize struct: Couldn't read eax (materialize)
। पहले के उत्तरों से जुड़े दस्तावेजों में वर्णित अन्य प्रयास भी विफल रहे।
कुंजी यह थी कि मुझे पहले objc_exception_throw
अपने मुख्य धागे में फ्रेम पर क्लिक करना था । lldb उस फ्रेम में शुरू नहीं होता है।
मेरे सभी खोज और निम्नलिखित उदाहरणों में, इस ब्लॉग प्रविष्टि ने चीजों को इस तरह से समझाने के लिए पहली बार किया था जो मेरे लिए काम करते थे। यह अधिक आधुनिक है, अगस्त 2012 में पोस्ट किया जा रहा है।
यदि आपके पास एक कैच स्टेटमेंट है, तो वहां एक विराम बिंदु रखें और आप उस बिंदु पर अपवाद ऑब्जेक्ट का निरीक्षण कर सकते हैं।
यदि आपके पास कैच स्टेटमेंट नहीं है, तो जारी रखें।
आपको अपने टर्मिनल में इस तरह एक संदेश मिलेगा:
अनकैप्ड अपवाद 'NSInvalidArgumentException' अपवाद के कारण ऐप समाप्त करना, कारण: ' * - [[__ NSPlaceholderDictionary initWithObjects: forKeys: count:]: ऑब्जेक्ट से ओएल ऑब्जेक्ट डालने का प्रयास [0]'
हालाँकि , आप शायद इसे जारी रखने के बिना निरीक्षण करने के लिए एक रास्ता तलाश रहे हैं क्योंकि आवेदन समाप्त होने पर आप अपना अच्छा स्टैक ट्रेस खो देंगे।
इसके लिए ऐसा लगता है कि Fnord का जवाब सबसे अच्छा है, लेकिन मैं इसे एलएलडीबी में काम करने में सक्षम नहीं था।