如何调试C#托管/非托管编组异常?

Diz*_*zzy 5 c# com debugging interop marshalling

我正在C#上编写DirectShow过滤器,但我不想使用任何第三方库。基于正确的COM接口原型(例如IGraphBuilder,IBaseFilter,IPin等),此任务几乎是100%。如果接口的原型不正确,则会在托管/本机边界引发各种异常。问题在于确定错误原型接口方法的位置。

当前,我有:DirectShow.dll中发生了'System.NullReferenceException'类型的异常(这是我的托管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!Thread :: WaitSuspendEventsHelper()+ 0xcf字节clr.dll!Thread :: WaitSuspendEvents()+ 0x10字节
clr.dll!string“ d:\ iso_whid \ amd64fre \ base \ ntos \ r“ ...()+ 0x35688d字节
clr.dll!Thread :: RareDisablePreemptiveGC()+ 0x118字节
clr.dll!GCHolderEEInterface <0,0,0> :: ~~ GCHolderEEInterface <0,0,0>() + 0x19字节clr.dll!Debugger :: SendCatchHandlerFound()+ 0x150字节
clr.dll!string“ d:\ iso_whid \ amd64fre \ base \ ntos \ r” ...()+ 0x3b9340字节
clr.dll!NotifyOfCHFFilterWrapper()+ 0x77字节
clr.dll!string“ d:\ iso_whid \ amd64fre \ base \ ntos \ r“ ...()+ 0x336941字节
msvcr100_clr0400.dll!__ C_specific_handler()+ 0x97字节
ntdll.dll!RtlpExecuteHandlerForException()+ 0xd字节ntdll.dll!RtlDispatchatchException()+ 0x38f字节ntdll.dll!KiUserExceptionDispatch( )+
0x2e 字节KernelBase.dll!RaiseException()+ 0x3d字节
clr.dll!NakedThrowHelper2()+ 0xc字节
clr.dll!NakedThrowHelper_RspAligned()+ 0x3d字节clr.dll!NakedThrowHelper_FixRsp()+ 0x5字节
000007ff00179
!clr.dll COMToCLRDispatchHelper()+ 0x4e字节
clr.dll SecurityDeclarative :: CheckLinkDemandAgainstAppDomain() - !0x40e字节
!clr.dll COMToCLRWorkerBody()+ 0xd6字节
!clr.dll COMToCLRWorkerDebuggerWrapper()+ 0×22字节
!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字节
crystal.dll!CFilterGraph :: FindUpstreamInterface()+ 0x171字节quartz.dll!CFilterGraph :: FindUpstreamInterface()+ 0xc1字节
quartz.dll!CWaveSlave :: UpdateSlaveMode()+ 0xa7字节
quartz.dll!CWaveOutInputPin :: RemovePreroll()+位0x95字节
的Quartz.dll!CWaveOutInputPin ::获得()+ 0x12f字节
msmpeg2adec.dll!CBaseOutputPin ::交付()+ 0×22字节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. 从本地到托管过渡->如果在此处引发异常,则仅编组步骤3的xxx,但我们处在茫茫荒野中。
  3. 名为xxx的托管代码方法。

因此,这无助于我,我也不知道如何调试它。

Han*_*ant 4

很难调试,故障发生在您没有编写的代码中。慢慢诊断这个问题。编写一个本机测试程序,获取要测试的接口指针,并按 v 表顺序一一验证方法。坏的就会跳出来。

请注意,C# 不支持多重继承。任何从非 IUnknown 或 IDispatch 的接口继承的 COM 接口都要求您重复基接口中方法的声明。忘记这样做会导致调用错误的方法。或者因为 v 表太短而不存在。NullReference 或 AccessViolation 是常见的结果。