إكس كود/LLDB:كيفية الحصول على معلومات حول الاستثناء الذي تم طرحه للتو؟

StackOverflow https://stackoverflow.com/questions/3327828

سؤال

حسنًا، تخيل أن نقطة التوقف الخاصة بي موجودة 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)

نصائح أخرى

على أجهزة المحاكاة الجديدة (iOS 8، 64 بت) xcode 6 im المستخدمة في إطار الاستثناء: objc_exception_throw

po $rax

في 32 بت:

po $eax

ما هو راكس؟

Rax هو سجل 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.

إذا كان لديك عبارة Catch، فضع نقطة توقف هناك ويمكنك فحص كائن الاستثناء عند تلك النقطة.

إذا لم يكن لديك بيان الالتقاط، تابع.

ستصلك رسالة في جهازك مثل هذه:

إنهاء التطبيق بسبب الاستثناء غير المُكتشف "NSInvalidArgumentException"، السبب:'* -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]:محاولة إدراج كائن لا شيء من الكائنات[0]'

لكن, ، ربما كنت تبحث عن طريقة لفحصه دون المتابعة لأنك ستفقد تتبع المكدس الرائع عند إنهاء التطبيق.

لذلك يبدو أن إجابة Fnord هي الأفضل، لكنني لم أتمكن من تشغيلها في LLDB.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top