Как отлаживать управляемые / неуправляемые исключения C # для маршаллинга? - PullRequest
4 голосов
/ 04 июля 2011

Я пишу фильтр DirectShow на C # и не хочу использовать какую-либо стороннюю библиотеку. Эта задача почти на 100% основана на правильном прототипировании COM-интерфейсов, таких как IGraphBuilder, IBaseFilter, IPin и т. Д. И если интерфейс прототипируется некорректно, возникают различные исключения на управляемых / собственных границах. Проблема состоит в том, чтобы определить местоположение неправильно прототипированного метода интерфейса.

В настоящее время у меня есть: Исключение типа «System.NullReferenceException» произошло в DirectShow.dll (это имя моей управляемой библиотеки DLL) и не было обработано до управляемой / собственной границы

Стек вызовов:

ntdll.dll! NtWaitForSingleObject () + 0xa байт
KernelBase.dll! WaitForSingleObjectEx () + 0x9c байт
clr.dll! CLREvent :: WaitEx () + 0x20f байт
clr.dll! CLREvent :: WaitEx () + 0x1b8 байт
clr.dll! CLREvent :: WaitEx () + 0x73 байта
clr.dll! Тема :: WaitSuspendEventsHelper () + 0xcf байт clr.dll! Тема :: WaitSuspendEvents () + 0x10 байт
clr.dll! строка "d: \ iso_whid \ amd64fre \ base \ ntos \ r" ... () + 0x35688d байт
clr.dll! Тема :: RareDisablePreemptiveGC () + 0x118 байт
clr.dll! GCHolderEEInterface <0,0,0> :: ~ GCHolderEEInterface <0,0,0> () + 0x19 байт clr.dll! Отладчик :: SendCatchHandlerFound () + 0x150 байт
clr.dll! строка "d: \ iso_whid \ amd64fre \ base \ ntos \ r" ... () + 0x3b9340 байт
clr.dll! NotifyOfCHFFilterWrapper () + 0x77 байт
clr.dll! строка "d: \ iso_whid \ amd64fre \ base \ ntos \ r" ... () + 0x336941 байт
msvcr100_clr0400.dll! __ C_specific_handler () + 0x97 байт
ntdll.dll! RtlpExecuteHandlerForException () + 0xd байт ntdll.dll! RtlDispatchException () + 0x38f байт ntdll.dll! KiUserExceptionDispatch () + 0x2e байт
KernelBase.dll! RaiseException () + 0x3d байт
clr.dll! NakedThrowHelper2 () + 0xc байт
clr.dll! NakedThrowHelper_RspAligned () + 0x3d байт clr.dll! NakedThrowHelper_FixRsp () + 0x5 байт
000007ff00179486 ()
clr.dll! COMToCLRDispatchHelper () + 0x4e байт
clr.dll! SecurityDeclarative :: CheckLinkDemandAgainstAppDomain () - 0x40e байт
clr.dll! COMToCLRWorkerBody () + 0xd6 байт
clr.dll! COMToCLRWorkerDebuggerWrapper () + 0x22 байта
clr.dll! COMToCLRWorker () + 0x201 байт clr.dll! GenericComCallStub () + 0x57 байт
[Родной для управляемого перехода]
quartz.dll! CEnumConnectedPins :: CEnumConnectedPins () + 0x4a байт
quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0x150 байт quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0xc1 байт
quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0x171 байт quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0xc1 байт
quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0x171 байт quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0xc1 байт
quartz.dll! CWaveSlave :: UpdateSlaveMode () + 0xa7 байт
quartz.dll! CWaveOutInputPin :: RemovePreroll () + 0x95 байт
quartz.dll! CWaveOutInputPin :: Receive () + 0x12f байт
msmpeg2adec.dll! CBaseOutputPin :: Deliver () + 0x22 байта msmpeg2adec.dll! CIVIAudioFilter :: DeliverOutSample () + 0x3da байт
msmpeg2adec.dll! CIVIAudioCodec :: DecodeDDPlus () + 0x556 байт
msmpeg2adec.dll! CIVIAudioCodec :: DecodeAll () + 0x121 байт
msmpeg2adec.dll! CIVIAudioFilter :: Process () + 0xda7 байт
msmpeg2adec.dll! CIVIAudioFilter :: Receive () + 0x16d байт
msmpeg2adec.dll! CTransformInputPin :: Receive () + 0x4c байт msmpeg2adec.dll! CIVIAudioInPin :: Receive () + 0x3f байт quartz.dll! CBaseOutputPin :: Deliver () + 0x22 байта
quartz.dll! CBaseMSRWorker :: TryDeliverSample () + 0x14f байт
quartz.dll! CBaseMSRWorker :: PushLoop () + 0x1da байт
quartz.dll! CBaseMSRWorker :: ThreadProc () + 0x90 байт
quartz.dll! CAMThread :: InitialThreadProc () + 0x1c байт kernel32.dll! BaseThreadInitThunk() + 0xd байтов ntdll.dll! RtlUserThreadStart () + 0x21 байтов

Другими словами, конвейер выглядит так:

  1. Функция собственного кода с именем CEnumConnectedPins ()
  2. Относительно управляемого перехода -> Если здесь выдается исключение, то xxx из шага 3 известен только маршаллеру, но мы находимся в глуши.
  3. Метод управляемого кода с именем xxx.

Так что это никуда меня не приведет, и я не знаю, как это отладить.

1 Ответ

3 голосов
/ 04 июля 2011

Это очень некрасиво для отладки, сбой происходит в коде, который вы не написали.Идите медленнее, чтобы диагностировать это.Напишите собственную тестовую программу, которая получает указатель интерфейса, который вы хотите протестировать, и проверяйте методы один за другим в порядке v-таблицы.Плохое выскочит.

Остерегайтесь того, что C # не поддерживает множественное наследование.Любой интерфейс COM, который наследуется от другого интерфейса, который не является IUnknown или IDispatch, требует повторения объявлений методов в базовом интерфейсе.Забыв об этом, вы вызываете неправильный метод.Или несуществующий, так как v-таблица слишком короткая.Тогда NullReference или AccessViolation являются обычным результатом.

...