Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么从32位comiled版本的应用程序调用本机代码而不是从64位版本调用本机代码时,会出现AccessViolationException < >我从我的C托管代码中调用了一些C++本地代码。当从64位或任何CPU编译的应用程序加载此dll时,一切都能正常工作。当它从32位应用程序加载时,我在调用InitializeSecurityContextW方法时得到一个AccessViolationException。本机方法的定义如下: [DllImport(SECUR32DLL, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] private static extern StatusEnum InitializeSecurityContextW( [In] ref HandleStruct handle1, [In] IntPtr handle2, [In] String str, [In] uint flags1, [In] uint reserved1, [In] uint flags2, [In] IntPtr bufferDesc, [In] uint reserved2, [In, Out] ref HandleStruct handleOut, [In, Out] BufferDescriptor bufferDescOut, [Out] out uint flagsOut, [Out] out long expiryOut);_C#_Clr_Pinvoke - Fatal编程技术网

C# 为什么从32位comiled版本的应用程序调用本机代码而不是从64位版本调用本机代码时,会出现AccessViolationException < >我从我的C托管代码中调用了一些C++本地代码。当从64位或任何CPU编译的应用程序加载此dll时,一切都能正常工作。当它从32位应用程序加载时,我在调用InitializeSecurityContextW方法时得到一个AccessViolationException。本机方法的定义如下: [DllImport(SECUR32DLL, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] private static extern StatusEnum InitializeSecurityContextW( [In] ref HandleStruct handle1, [In] IntPtr handle2, [In] String str, [In] uint flags1, [In] uint reserved1, [In] uint flags2, [In] IntPtr bufferDesc, [In] uint reserved2, [In, Out] ref HandleStruct handleOut, [In, Out] BufferDescriptor bufferDescOut, [Out] out uint flagsOut, [Out] out long expiryOut);

C# 为什么从32位comiled版本的应用程序调用本机代码而不是从64位版本调用本机代码时,会出现AccessViolationException < >我从我的C托管代码中调用了一些C++本地代码。当从64位或任何CPU编译的应用程序加载此dll时,一切都能正常工作。当它从32位应用程序加载时,我在调用InitializeSecurityContextW方法时得到一个AccessViolationException。本机方法的定义如下: [DllImport(SECUR32DLL, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] private static extern StatusEnum InitializeSecurityContextW( [In] ref HandleStruct handle1, [In] IntPtr handle2, [In] String str, [In] uint flags1, [In] uint reserved1, [In] uint flags2, [In] IntPtr bufferDesc, [In] uint reserved2, [In, Out] ref HandleStruct handleOut, [In, Out] BufferDescriptor bufferDescOut, [Out] out uint flagsOut, [Out] out long expiryOut);,c#,clr,pinvoke,C#,Clr,Pinvoke,使用以下结构和枚举: public struct HandleStruct { private IntPtr Low; private IntPtr High; public bool IsZero { return Low == IntPtr.Zero && High == IntPtr.Zero; } } private enum StatusEnum { // Values here. } [Struc

使用以下结构和枚举:

public struct HandleStruct
{
    private IntPtr Low;
    private IntPtr High;

    public bool IsZero
    {
        return Low == IntPtr.Zero && High == IntPtr.Zero;
    }
}

private enum StatusEnum {
     // Values here.
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
private struct BufferDescriptor
{
    public uint Version;
    public uint Count;
    public IntPtr BufferArray;
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
private struct Buffer
{
    public uint Size;
    public uint Type;
    public IntPtr Data;
}
(简化)呼叫代码为:

Buffer[] bufferOut = new Buffer[1];
bufferOut[0].Size = 0;
bufferOut[0].Type = 2; // Token type
bufferOut[0].Data = IntPtr.Zero; // I'm asking the server to allocate this memory (unmanaged).

GCHandle bufferOutPtr = GCHandle.Alloc(bufferOut, GCHandleType.Pinned);

BufferDescriptor bufferDescOut = new BufferDescriptor();
bufferDescOut.Count = 1;
bufferDescOut.Version = 0; // Version number
bufferDescOut.BufferArray = bufferOutPtr.AddrOfPinnedObject();

uint flags1 = // Some flags here including asking the server to allocate memory;
uint flags2 = 0; //data representation

uint flagsOut;
long expiry;

StatusEnum status = InitializeSecurityContextW(
    ref handle1, // From calling method
    IntPtr.Zero, // Null for this call
    str, // From calling method
    flags1,
    0,
    flags2,
    IntPtr.Zero, // Null for this call
    0,
    ref handleOut, // From calling method, currently handleOut.IsZero == true
    bufferDescOut,
    out flagsOut,
    out expiry);

// Clean up code, never reached.

为什么会发生这种情况,为什么只有32位?

我需要固定输出缓冲区描述符并传递地址,而不是整个结构。

就我个人而言,我不会考虑64位版本似乎没有显示错误这一事实。如果32位与AccessViolationException一起失败,则说明本机代码中存在错误,或者一个或多个对象未正确固定。如果我不得不冒险猜一猜(即,我可能错了很多),64位可能不会显示符号,因为地址空间太大(按大小),代码中的错误可能不会轻易触发访问冲突错误。@VikasGupta我一直认为是这样的。垃圾收集器在32位压缩方面更具攻击性,因为它的内存更少,而且它正在移动未固定的东西,但恰好在64位中没有移动。但是我看不出有什么没有被锁定的东西需要被锁定,可以吗?@VikasGupta也不可能在本机代码中有错误,因为我也有一个本机实现,它直接调用相同的方法(使用非常相似的逻辑),在任何情况下都不会像这样失败。我从来没有处理过很多互操作,因此,我并不声称自己是这里的专家(只有基本知识-希望我可以调试自己的代码,如果需要的话),但您可以将调用InitializeSecurityContextW的代码与pinvoke.net(著名的pinvoke签名网站)上提供的签名和示例代码进行比较-我可以看到的一个区别是您有
[In]ref IntPtr bufferDesc,
vs pinvoke.net
IntPtr pInput,
。。i、 e.您通过引用传递IntPtr。。是吗?你的意思是声明
ref BufferDescriptor bufferDescOut
vs实际调用
bufferDescOut,
编译器没有抱怨你没有通过ref吗?@VikasGupta没有,看起来无效的ref是打字错误。我修正了这个问题以反映真实情况。很抱歉。