C++转VB.NET:readMemory函数调用引发访问违规异常求助
问题分析与解决方法
核心问题拆解
你的代码存在三个关键错误,直接导致了访问违规和参数异常:
- 调用时参数传错:调用
readMemory时第三个参数硬编码为0,而非你定义的size=1,函数读取内存的大小逻辑完全错误。 - 参数类型不匹配引发栈错乱:C++函数的
address是32位unsigned int,你传入64位UInt64会破坏栈帧结构,导致后续size参数被错误读取,出现随机值。 - 输出参数未正确初始化:
dataStruct作为指向内存缓冲区的指针,未根据函数的内存处理逻辑做对应准备。
分步解决
1. 修正VB.NET函数声明
确保参数类型和调用约定严格匹配C++函数:
' 替换"你的DLL文件名"为实际库名称,调用约定根据C++函数实际情况调整(stdcall/cdecl) <System.Runtime.InteropServices.DllImport("你的DLL文件名", CallingConvention:=System.Runtime.InteropServices.CallingConvention.StdCall)> Public Function readMemory( ByVal address As UInteger, ByRef data As IntPtr, ByVal size As UInteger) As Integer End Function
如果C++函数使用__cdecl调用约定,需将CallingConvention改为CallingConvention.Cdecl,否则会引发栈不平衡异常。
2. 正确调用函数
根据C++函数的内存处理逻辑,分两种情况调整:
情况1:C++要求预先分配内存
如果函数需要你提供已分配的缓冲区来存储读取结果:
Dim startAddress As UInteger = &H801FFFA Dim size As UInteger = 1 ' 分配对应大小的非托管内存 Dim dataStruct As IntPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(CInt(size)) Dim readMemoryFlag As Integer = 0 ' 传入正确的size参数 readMemoryFlag = readMemory(startAddress, dataStruct, size) ' 读取并处理数据(示例:转换为Byte) If readMemoryFlag = 0 Then ' 假设返回0表示读取成功 Dim readValue As Byte = System.Runtime.InteropServices.Marshal.ReadByte(dataStruct) ' 这里添加你的业务逻辑 End If ' 释放非托管内存,避免泄漏 System.Runtime.InteropServices.Marshal.FreeHGlobal(dataStruct)
情况2:C++内部分配内存并返回指针
如果函数会自行分配内存,通过data参数返回指针:
Dim startAddress As UInteger = &H801FFFA Dim size As UInteger = 1 Dim dataStruct As IntPtr = IntPtr.Zero Dim readMemoryFlag As Integer = 0 readMemoryFlag = readMemory(startAddress, dataStruct, size) If readMemoryFlag = 0 AndAlso dataStruct <> IntPtr.Zero Then Dim readValue As Byte = System.Runtime.InteropServices.Marshal.ReadByte(dataStruct) ' 这里添加你的业务逻辑 ' 注意:必须调用C++提供的内存释放函数(如对应free的封装函数)来释放内存,避免泄漏 ' 示例:freeMemory(dataStruct) End If
3. 验证地址有效性
&H801FFFA必须是当前进程中具有读取权限的合法内存地址,如果地址本身无效(如不属于当前进程、无读取权限),即使参数正确也会触发访问违规。可以通过内存工具(如Cheat Engine)确认地址的合法性。
内容的提问来源于stack exchange,提问作者Luke W
相关产品推荐
相关产品推荐

