يختلف سلوك تصحيح الأخطاء بين التطبيق غير المدير والمختلط (غير المدير+المدارة)؟

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

  •  26-09-2019
  •  | 
  •  

سؤال

خذ المصدر البسيط التالي (اسم test.cpp):

#include <windows.h>

void main()
{
DebugBreak();
}

تجميع وربط هذا باستخدام الأوامر التالية:

cl /MD /c test.cpp
link /debug test.obj

إذا تم تشغيل test.exe الآن (على نظام Windows 7 64 بت) ، يمكنك الحصول على مربع الحوار التالي:

DebugBreak in unmanaged application

أضف الآن الملف المصدر التالي (اسمه test2.cpp):

void hello()
{
}

وتجميع هذا وربط هذا مع المصدر الأول ، مثل هذا:

cl /MD /c       test.cpp
cl /MD /c /clr  test2.cpp
link test.obj test2.obj

لاحظ أننا لم نتصل بالوظيفة Hello ، لقد ربطناها فقط.

الآن قم بتشغيل Test.exe مرة أخرى (على نفس نظام Windows 7 64 بت). بدلاً من الحوار الموضح أعلاه ، ستحصل على هذا:

DebugBreak in mixed-mode application

على ما يبدو ، فإن الارتباط في إطار .NET يجعل تصحيح الأخطاء يتصرف بشكل مختلف. لماذا هذا؟ وكيف يمكنني استعادة سلوك التصحيح القديم مرة أخرى؟ هل هذا ربما سلوك Windows 7 أو 64 بت؟

علامة جانبية لتوضيح سبب رغبتي في استخدام تصحيح الأخطاء: لدينا مجموعة مؤكدة مخصصة (شيء مثل Superassert من كتاب تطبيقات Windows من John Robbin) ، وأنا أستخدم وظيفة DebugBreak حتى يتمكن المطور من القفز إلى مصحح الأخطاء ( أو افتح تصحيح أخطاء جديد) إذا كانت هناك مشكلة. الآن لا يوجد سوى نافذة منبثقة بسيطة ولا توجد إمكانية للقفز إلى مصحح الأخطاء بعد الآن.

كحل بديل ، يمكنني تنفيذ مقسم لكل صفر أو كتابة إلى عنوان غير صالح ، لكنني أجد هذا حلًا أقل نظافة.

تعديل:هذا هو مكدس المكالمات في الاختبار الثاني (مربع الحوار البسيط):

ntdll.dll!_NtRaiseHardError@24()  + 0x12 bytes  
ntdll.dll!_NtRaiseHardError@24()  + 0x12 bytes  
clrjit.dll!Compiler::compCompile()  + 0x5987 bytes  
clr.dll!RaiseFailFastExceptionOnWin7()  + 0x6b bytes    
clr.dll!WatsonLastChance()  + 0x1b8 bytes   
clr.dll!InternalUnhandledExceptionFilter_Worker()  + 0x29c bytes    
clr.dll!InitGSCookie()  + 0x70062 bytes 
clr.dll!__CorExeMain@0()  + 0x71111 bytes   
msvcr100_clr0400.dll!@_EH4_CallFilterFunc@8()  + 0x12 bytes 
msvcr100_clr0400.dll!__except_handler4_common()  + 0x7f bytes   
clr.dll!__except_handler4()  + 0x20 bytes   
ntdll.dll!ExecuteHandler2@20()  + 0x26 bytes    
ntdll.dll!ExecuteHandler@20()  + 0x24 bytes 
ntdll.dll!_KiUserExceptionDispatcher@8()  + 0xf bytes   
KernelBase.dll!_DebugBreak@0()  + 0x2 bytes 
test_mixed.exe!01031009()   

هذا هو مكدس المكالمات في الاختبار الأول (مربع حوار مع خيارات "إغلاق" و "Debug"):

ntdll.dll!_ZwWaitForMultipleObjects@20()  + 0x15 bytes  
ntdll.dll!_ZwWaitForMultipleObjects@20()  + 0x15 bytes  
kernel32.dll!_WaitForMultipleObjectsExImplementation@20()  + 0x8e bytes 
kernel32.dll!_WaitForMultipleObjects@16()  + 0x18 bytes 
kernel32.dll!_WerpReportFaultInternal@8()  + 0x124 bytes    
kernel32.dll!_WerpReportFault@8()  + 0x49 bytes 
kernel32.dll!_BasepReportFault@8()  + 0x1f bytes    
kernel32.dll!_UnhandledExceptionFilter@4()  + 0xe0 bytes    
ntdll.dll!___RtlUserThreadStart@8()  + 0x369cc bytes    
ntdll.dll!@_EH4_CallFilterFunc@8()  + 0x12 bytes    
ntdll.dll!ExecuteHandler2@20()  + 0x26 bytes    
ntdll.dll!ExecuteHandler@20()  + 0x24 bytes 
ntdll.dll!_KiUserExceptionDispatcher@8()  + 0xf bytes   
KernelBase.dll!_DebugBreak@0()  + 0x2 bytes 
test_native.exe!00af1009()  

يبدأ الفرق في ntdll.dll !executeHandler2@20. في تطبيق غير ntdll.dll!@_EH4_CallFilterFunc. في تطبيق .NET هو المكالمات clr.dll!__except_handler4.

هل كانت مفيدة؟

المحلول

لقد وجدت الحل في الصفحة التالية: http://www.codeproject.com/kb/debug/debugbreakanyway.aspx.

بدلاً من مجرد كتابة تصحيح الأخطاء ، يجب عليك تضمين مكالمة تصحيح الأخطاء بين __try/__ باستثناء البناء ، مثل هذا:

__try
   {
   DebugBreak();
   }
__except (UnhandledExceptionFilter(GetExceptionInformation()))
   {
   }

على ما يبدو ، تعالج وظيفة UnhandleDexceptionFilter استثناء تصحيح الأخطاء افتراضيًا ، والذي يبدو أنه تم نقضه في تطبيقات مختلطة.

الآن يمكنك استعادة الحوار الأصلي مرة أخرى.

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