pInvoke, .net 4 vs 3.5

2019-08-13 13:08发布

问题:

I've an issue regarding p/invoke from managed to unmanaged code. See my original post at the MSDN forum (as brief summary is seen later in this post). Before I go on, I just want to explain a couple of things: I have a wrapper assembly in net 3.5 that does the actual interop to the unmanaged code. Then I have my console "host app" which uses the wrapper assembly.

The solution I came up (I refer to my MSDN post) works when the host app is using .net 4, but it doesn't work when changing the host app to use .net 3.5. When changing, I get a AccessViolationException.

  • host app: 4.0, wrapper assembly: 3.5 -> works
  • host app: 3.5, wrapper assembly: 3.5 -> throws AccessViolationException

Do anyone have a clue to why I get an AccessViolationException? Most importantly, how do I get it working with .net 3.5?

Brief summary on the MSDN post I refered to. I have this messy p/Invoke I need to solve. The C declaration looks like this:

long TBAPI TbeAndring (short, 
            short,
            PTB_PU,
            PTB_ANDRING_INFO,
            PTB_PARAMS,
            PTB_PREMIE_NIVA_INFO,
            PTB_PREMIE,
            PTB_FORMAN_INFO,
            PTB_FORMAN,
            PTB_FUNK,
            PTB_PARAMS,
            PTB_PREMIE_NIVA_INFO,
            PTB_PREMIE,
            PTB_FORMAN_INFO,
            PTB_FORMAN,
            PTB_FUNK);

Where PTB means that each argument is a struct pointer to an array of arbitrary length. The structs mostly contains strings, doubles, char and short. Anyway, I ended up with this DllImport statement:

<DllImport(NativeLibraryName, CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi, SetLastError:=True)>
  Public Shared Function TbeAndring(ByVal sAntMoment As Short, _
                   ByVal sAntPU As Short, _
                   <[In]()> ByVal atbpu As PTB_PU(), _
                   <[In]()> ByVal atbandringinfo() As PTB_ANDRING_INFO, _
                   <[In]()> ByVal atbparamsEfter() As PTB_PARAMS, _
                   <[In]()> ByVal aNivaInfoEfter() As PTB_PREMIE_NIVA_INFO, _
                   <[In](), Out()> ByVal atbpremieEfter() As PTB_PREMIE, _
                   <[In]()> ByVal atbFormanInfoEfter() As PTB_FORMAN_INFO, _
                   <[In](), Out()> ByVal atbFormanEfter() As PTB_FORMAN, _
                   <[In](), Out()> ByVal atbfunkEfter() As PTB_FUNK, _
                   <[In]()> ByVal atbparamsFore() As PTB_PARAMS, _
                   <[In]()> ByVal aNivaInfoFore() As PTB_PREMIE_NIVA_INFO, _
                   <[In](), Out()> ByVal atbpremieFore() As PTB_PREMIE, _
                   <[In]()> ByVal atbFormanInfoFore() As PTB_FORMAN_INFO, _
                   <[In](), Out()> ByVal atbFormanFore() As PTB_FORMAN, _
                   <[In](), Out()> ByVal atbfunkFore() As PTB_FUNK) As Int32
  End Function

As you see some of the arguments are changed by the unmanaged code as well.

回答1:

I don't know if it's the only reason for AccessViolationException, but I've seen that exception come from unmanaged code that was running with a corrupt C runtime library heap. In particular, some memory which was meant to contain a valid pointer came to contain garbage: when dereferenced, it pointed to nonexistant memory.

If you have an issue like this, then the change in .NET version may simply have moved the problem around, such that the problem has been seen under .NET 3.5 but has not yet been seen under .NET 4.0.

I recommend running the code under the debugger, and including Native code debugging. You may find the original exception.