그것이 관리 예외가 을 던져 관리 코드에 걸려 있지만, 어디 개입 기본 프레임이 호출 스택에가있을 수 있습니까?는 기본 프레임
이 작업을 수행하는 데 문제가 있습니다. 응용 프로그램은 32 비트 네이티브 코드이며 MSCLR 2.0을 호스팅합니다. 그러나 대부분의 코드는 .NET 3.5입니다.
이 throw가 완료되지 않으면 응용 프로그램이 제대로 실행되고 던지기 만하면 정확히 실행됩니다. 시스템을 실행 중입니다.
실제 응용 프로그램은 상당히 복잡하므로 처음에는 일러스트레이션을 위해 간단한 개념 코드를 게시 할 것입니다. 네이티브 프로그램 (Native.exe
)은 하나의 관리되는 프로그램을 실행하며 Managed.exe
이라고합니다. 어딘가 Managed.exe
내에서, C#으로 작성된, 다음입니다 :
class MyException : Exception {}
...
void OuterManaged()
{
MyObject.MyEvent += (s, a) =>
{
Console.WriteLine("Throwing...");
throw new MyException();
}
try
{
MyKernel.DoSomething();
Console.WriteLine("Finished");
} catch(MyException)
{
Console.WriteLine("Caught");
}
}
MyKernel
우리가 Glue.dll
전화 할게 ++/CLI 어셈블리 혼합 C에 정의 된 관리 클래스입니다. MyObject
은 Glue.dll
에 다른 클래스의 인스턴스입니다.
void DoSomething(void)
{
_pMyNativeKernel->DoSomething();
}
DoSomething
사실상라고 Native.exe
에서 C++ 함수 : 거기에 관련하는 메소드는 다음과 같이 보인다. 긴 이야기를 짧게하기 위해 결국 Glue.dll
의 관리 방법을 다시 호출하여 MyEvent
을 발생시킵니다. 윈도우 7 64 비트 시스템에서 실행
Throwing...
Caught
을 내가 대신 : MyEvent
가 발생하고 프로그램이 32 비트 Windows XP 시스템에서 실행중인
경우 의도 콘솔이 표시됩니다, 그것은 작동 이것을 얻으십시오 :
Throwing...
Finished
기본적으로, 예외는 다만 허공으로 사라집니다. 모든 일은 결코 일어난 적이없는 것처럼 계속 실행됩니다.
Throwing...
: (. 예외는 창 닫기 버튼을 눌렀을에 해당하는, 그래서 그냥 버튼을 클릭하지 않은 것처럼 역할)
원격 데스크톱을 통해 윈도우 서버 2012 시스템을 실행,이 수 대화 상자가 말하는 "Native.exe의 작동이 중지되었습니다"이와
그리고 전체 응용 프로그램이 충돌은 :
Description:
Stopped working
Problem signature:
Problem Event Name: CLR20r3
Problem Signature 01: Native.exe
Problem Signature 02: 0.0.0.0
Problem Signature 03: 5267c484
Problem Signature 04: 0
Problem Signature 05: 1.0.0.0
Problem Signature 06: 5272e299
Problem Signature 07: 208
Problem Signature 08: f
Problem Signature 09: MyException
OS Version: 6.2.9200.2.0.0.144.8
Locale ID: 1033
이 내가이 try
/catch
없었다고 기대했을 것입니다.
VS2008SP 디버거에서 해당 환경에서 실행할 경우 디버거가 첫 번째 예외를 catch하고 계속하면 처리되지 않은 예외로 catch합니다.
네이티브 DoSomething
은 결국 Win32 GetMessage
을 호출하고 DispatchMessage
을 호출하고 네이티브 관리 식 콜백은 창 프로 시저에서 호출 된 코드에서 발생합니다. 이 창은 Direct3D로 그려져 있습니다.관리되는 프로그램은 모든 윈도우 및 그리기 작업에 Native.exe
"커널"을 사용하며 Windows 자체는 액세스하지 않습니다. Native.exe
캐치 전혀 예외의 중간 기능의
없음. Win32 API 함수에 예외 처리기가 있는지 말할 수 없습니다. 그렇게 생각하지는 않겠지 만 그럴 경우 행동이 시스템간에 어떻게 모순되는지 설명 할 수 있습니다. 반복적 인 항목을 잘라와
이것은 대략 서버 2012의 실제 호출 스택입니다 :이 모든 시스템은 오랜 시간 동안 잘 작동하고있다
Managed!MyGame.ReInitDisplay.AnonymousMethod(object s = {Engine.Display}, System.EventArgs a = {System.EventArgs}) C# // throw site
Glue.dll!CDisplayBridge::OnClosePressed() C++
[Native to Managed Transition]
Native.EXE!EngineKern::CGfxDisplay_a::HandleClosePress() C++
Native.EXE!EngineKern::CGfxDisplay::WindowProc(HWND__ * hwnd=0x000610ac, unsigned int uMsg=16, unsigned int wParam=0, long lParam=0) C++
user32.dll!74a477d8()
[Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]
user32.dll!74a47c44()
ntdll.dll!773e2f02()
user32.dll!74a48fed()
uxtheme.dll!7422254d()
user32.dll!74a475e7() // DefWindowProc
Native.EXE!EngineKern::CGfxDisplay::WindowProc(HWND__ * hwnd=0x000610ac, unsigned int uMsg=274, unsigned int wParam=61536, long lParam=4261024) C++
user32.dll!74a48a66() // DispatchMessage
Native.EXE!EngineKern::CKernel::DoEvent() C++
[Managed to Native Transition]
Glue.dll!Engine::Kernel::DoEvent() C++ // DoSomething in the example
MyClassLib!MyClassLib.Game.MainLoop() C#
MyClassLib!MyClassLib.Game.Play() C#
Managed!MyGame.Play() C#
Managed!Program.Main(string[] args = {string[0]}) C#
mscorlib.dll!System.AppDomain.ExecuteAssemblyByName(string assemblyName, System.Security.Policy.Evidence assemblySecurity, string[] args)
mscorlib.dll!System.AppDomain.ExecuteAssemblyByName(string assemblyName)
Glue.dll!__Engine__::AppDomainManager::Main(int pEngineKern = 15760932) C++
[Native to Managed Transition]
Native.EXE!EngineGlue::IManagedEntryPoint::Main(long pEngineKern=15760932) C++ // calls in by COM interop
Native.EXE!CClrHost::Run() C++
Native.EXE!wWinMain(HINSTANCE__ * hInstance=0x00e40000, HINSTANCE__ * hPrevInstance=0x00000000, wchar_t * lpCmdLine=0x01462a80, int nCmdShow=5) C++
Native.EXE!__tmainCRTStartup() C
Native.EXE!wWinMainCRTStartup() C
kernel32.dll!74ca8543()
ntdll.dll!773fac3c()
하지만 관리를 통해 나는 예외를 던질 필요하지 않습니다/이전의 네이티브 트랜지션. 네이티브 호스트가 네이티브에서 관리되는 콜백을 수행하는지 여부를 염려하지 않고 관리되는 응용 프로그램 코드에서 예외를 자유롭게 포착하고 catch 할 수 있기를 바랍니다.
내가 온라인 등의 전환을 통해 예외를 던지는에 대한 찾을 모든 정보가 네이티브 예외 또는 그 반대의 캐치를 관리하는 데 대해 항상이다. 이는 관리되는 catching 관리이지만 간섭하는 네이티브 프레임은 문제를 복잡하게 만듭니다.
그래서 일반적으로 다음과 같이 던지는에 관해서 내 질문은 :
이 일을해야 하는가? 이 은 Windows XP에서으로 작동하지만 잘 정의 된 동작인지 아니면 운이 좋았는지는 알 수 없습니다.
이 일 경우 모든 시스템에서 작동하지 않는 이유는 무엇입니까?
이 있다면 하지 다음 내가, 관리 예외를 잡기 위해 모든 관리 답신 전화를 증대 네이티브 예외로 포장 등에 대한 관리되는 래퍼에서 그것을 잡을해야 할 것 같아요 작동하도록되어 네이티브 함수와 원래의 관리 예외를 throw합니다. 머리카락을 많이 당기는 것처럼 들리네!
당신이 설명하는 문제는 http://stackoverflow.com/questions/6124631/clr-hosting-exception-handling-in-a-non-clr-created- 관련이있을 수 있습니다 thread? rq = 1. 관리되는 스레드에서 항상 콜백을 실행하는 데 도움이되는지 확인하십시오. – archgl
@archgl 팁 주셔서 감사. 제 경우에는 _unhandled_ 예외가 아니지만 다른 질문에 단서가 있습니다. 어쩌면 일어나는 일은 네이티브 프레임으로 인해 SEH 예외가되어 외부 관리 프레임이 catch를하지 않기 때문입니다. 오직 SEH가 아닌 원래 관리되는 예외를 잡으려고합니다. 나는 그것보다 더 똑똑하기를 바랐다. (M-> N 썽크 _ SEH를 잡아서 관리로 되돌려 야한다. 별도의 스레드에서 다시 호출하면 실제로 외부 관리 코드에서 예외를 _ 판단 할 수 없습니다. – Kevin