How to debug C # exceptions, managed / unmanaged exceptions?

I am writing a DirectShow filter in C # and I do not want to use a third-party library. This task is almost 100% based on the correct prototyping of COM interfaces such as IGraphBuilder, IBaseFilter, IPin, etc. And if the interface is not prototyped correctly, various exceptions will be thrown at the managed / internal borders. The problem is locating the method of the incorrectly prototyped interface.

Currently I have: An exception of type "System.NullReferenceException" occurred in DirectShow.dll (this is the name of my managed dll) and was not handled to the managed / internal border

Call stack:

ntdll.dll! NtWaitForSingleObject () + 0xa bytes
KernelBase.dll! WaitForSingleObjectEx () + 0x9c bytes
clr.dll! CLREvent :: WaitEx () + 0x20f bytes
clr.dll! CLREvent :: WaitEx () + 0x1b8 bytes
clr.dll! CLREvent :: WaitEx () + 0x73 bytes
clr.dll! Thread :: WaitSuspendEventsHelper () + 0xcf bytes clr.dll! Thread :: WaitSuspendEvents () + 0x10 bytes
clr.dll! string "d: \ iso_whid \ amd64fre \ base \ ntos \ r" ... () + 0x35688d bytes
clr.dll! Thread :: RareDisablePreemptiveGC () + 0x118 bytes
clr.dll! GCHolderEEInterface <0,0,0> :: ~ GCHolderEEInterface <0,0,0> () + 0x19 bytes clr.dll! Debugger :: SendCatchHandlerFound () + 0x150 bytes
clr.dll! string "d: \ iso_whid \ amd64fre \ base \ ntos \ r" ... () + 0x3b9340 bytes
clr.dll! NotifyOfCHFFilterWrapper () + 0x77 bytes
clr.dll! string "d: \ iso_whid \ amd64fre \ base \ ntos \ r" ... () + 0x336941 bytes
msvcr100_clr0400.dll! __ C_specific_handler () + 0x97 bytes
ntdll.dll! RtlpExecuteHandlerForException () + 0xd bytes ntdll.dll! RtlDispatchException () + 0x38f bytes ntdll.dll! KiUserExceptionDispatch () + 0x2e bytes
KernelBase.dll! RaiseException () + 0x3d bytes
clr.dll! NakedThrowHelper2 () + 0xc bytes
clr.dll! NakedThrowHelper_RspAligned () + 0x3d bytes clr.dll! NakedThrowHelper_FixRsp () + 0x5 bytes
000007ff00179486 ()
clr.dll! COMToCLRDispatchHelper () + 0x4e bytes
clr.dll! SecurityDeclarative :: CheckLinkDemandAgainstAppDomain () - 0x40e bytes
clr.dll! COMToCLRWorkerBody () + 0xd6 bytes
clr.dll! COMToCLRWorkerDebuggerWrapper () + 0x22 bytes
clr.dll! COMToCLRWorker () + 0x201 bytes clr.dll! GenericComCallStub () + 0x57 bytes
Transition to a managed transition

quartz.dll! CEnumConnectedPins :: CEnumConnectedPins () + 0x4a bytes
quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0x150 bytes quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0xc1 bytes
quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0x171 bytes quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0xc1 bytes
quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0x171 bytes quartz.dll! CFilterGraph :: FindUpstreamInterface () + 0xc1 bytes
quartz.dll! CWaveSlave :: UpdateSlaveMode () + 0xa7 bytes
quartz.dll! CWaveOutInputPin :: RemovePreroll () + 0x95 bytes
quartz.dll! CWaveOutInputPin :: Receive () + 0x12f bytes
msmpeg2adec.dll! CBaseOutputPin :: Deliver () + 0x22 bytes msmpeg2adec.dll! CIVIAudioFilter :: DeliverOutSample () + 0x3da bytes
msmpeg2adec.dll! CIVIAudioCodec :: DecodeDDPlus () + 0x556 bytes
msmpeg2adec.dll! CIVIAudioCodec :: DecodeAll () + 0x121 bytes
msmpeg2adec.dll! CIVIAudioFilter :: Process () + 0xda7 bytes
msmpeg2adec.dll! CIVIAudioFilter :: Receive () + 0x16d bytes
msmpeg2adec.dll! CTransformInputPin :: Receive () + 0x4c bytes msmpeg2adec.dll! CIVIAudioInPin :: Receive () + 0x3f bytes quartz.dll! CBaseOutputPin :: Deliver () + 0x22 bytes
quartz.dll! CBaseMSRWorker :: TryDeliverSample () + 0x14f bytes
quartz.dll! CBaseMSRWorker :: PushLoop () + 0x1da bytes
quarez.dll! CBaseMSRWorker :: ThreadProc () + 0x90 bytes
quartz.dll! CAMThread :: InitialThreadProc () + 0x1c bytes kernel32.dll! BaseThreadInitThunk () + 0xd bytes ntdll.dll! RtlUserThreadStart () + 0x21 bytes

In other words, the pipeline:

  • An internal code function called CEnumConnectedPins ()
  • Transition from managed to managed → If an exception is selected here, then xxx from step 3 is known only to the marshaller, but we are not located anywhere.
  • A managed code method named xxx.

So this is not going anywhere, and I do not know how to debug it.

+4
source share
1 answer

This is very ugly for debugging, an error occurs in code that you did not write. Go slower to diagnose this. Write your own test program that gets the pointer of the interface you want to test and test the methods one by one in v-table order. A bad one will appear.

Beware that C # does not support multiple inheritance. Any COM interface that inherits from another interface that is not IUnknown or IDispatch requires repeating method declarations in the base interface. Forgetting to do this calls the wrong method to call. Or nonexistent as the v-table is too short. NullReference or AccessViolation is the overall result.

+3
source

All Articles