有人可以解释一下为什么会这样吗:
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Class MEMORYSTATUSEX
Public Sub New()
Me.dwLength = CType(Marshal.SizeOf(GetType(MEMORYSTATUSEX)), UInt32)
End Sub
Public dwLength As UInt32
Public dwMemoryLoad As UInt32
Public ullTotalPhys As UInt64
Public ullAvailPhys As UInt64
Public ullTotalPageFile As UInt64
Public ullAvailPageFile As UInt64
Public ullTotalVirtual As UInt64
Public ullAvailVirtual As UInt64
Public ullAvailExtendedVirtual As UInt64
End Class
这不会:
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Structure MEMORYSTATUSEX
Public Sub New(ByVal dwlength As UInt32)
Me.dwLength = dwlength
End Sub
Public dwLength As UInt32
Public dwMemoryLoad As UInt32
Public ullTotalPhys As UInt64
Public ullAvailPhys As UInt64
Public ullAvailPageFile As UInt64
Public ullTotalVirtual As UInt64
Public ullAvailVirtual As UInt64
Public ullAvailExtendedVirtual As UInt64
End Structure
当从另一个类调用两个结构/类时,如下所示:
Dim newpoint As New Structures.MEMORYSTATUSEX()
GlobalMemoryStatusEx(newpoint)
第二个:
Dim newpoint As New Structures.MEMORYSTATUSEX(CType(Marshal.SizeOf(GetType(Structures.MEMORYSTATUSEX)), UInt32))
GlobalMemoryStatusEx(newpoint)
它们都在一个类中,当我使用大小参数调用第二个类时,它会在 GlobalMemoryStatusEx(newpoint)
调用上抛出“第一次机会出现 AccessViolationException”并使应用程序崩溃。
我不明白为什么 dwLength 值是在构造函数中初始化的?我说得对吗?
我想更改第一个示例的原因是因为我将所有结构移动到仅结构类,并且认为这将是一个好主意,直到我无法理解为什么这不起作用,因为在调用 API 之前设置相同的值。
P/调用声明:
<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function GlobalMemoryStatusEx(lpBuffer As Structures.MEMORYSTATUSEX) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
错误详细信息:
Client.exe 中第一次出现“System.AccessViolationException”类型的异常
其他信息:尝试读取或写入 protected 内存...
如果我点击继续:
mscorlib.dll 中发生了“System.Reflection.TargetInitationException”类型的第一次机会异常
附加信息:调用目标已引发异常
最佳答案
Private Shared Function GlobalMemoryStatusEx(lpBuffer As Structures.MEMORYSTATUSEX) ...
lpBuffer
参数是一个指针。必需的,以便函数可以写入结构成员。指针在 VB.NET 中隐藏得很好,如果使用不当,它们就会把程序炸成碎片。可能发生的事故有很多,AccessViolationException 是较温和的一种。
在 VB.NET 中获取指针的两种基本方法。您可以声明一个参数 ByRef
如果参数是值类型。或者,如果它是引用类型(Class 关键字),则引用在运行时自动变为指针,并且应传递 ByVal
.
因此,有效的组合是通过 ByRef 传递的结构或通过 ByVal 传递的类。类还需要显式 <StructLayout>
强制 CLR 以可预测的方式对其字段进行排序。您可以通过结构免费获得它。因此这是合乎逻辑的选择。
您应该使用 My.Computer.Info,它已经为您 pinvokes GlobalMemoryStatusEx()。
关于vb.net - 调用类与结构时抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24456975/