从 dll 使用 CopyMemory 并抛出访问冲突错误
Using CopyMemory from dll and throwing Access Violation Error
我创建了一个用于 Unity5 C# 程序的 C++ .dll 库。
但是,当我 运行 来自 Unity 编辑器的程序并尝试调用 smCopy 时,Unity 崩溃并尝试发送错误报告;相反,我追踪到该错误是从 smCopy 发生的访问冲突错误。
.dll 库允许我连接到服务器并通过此函数将数据复制到给定参数中:
C++:
void DLL_API smCopy(const VOID *dest, SIZE_T len)
{
CopyMemory((PVOID)(dest), (PVOID)(mapBuffer), len);
}
在我的 Unity 脚本中,我导入函数:
C#:
[DllImport(DLL_NAME, EntryPoint = "smCopy")]
private static extern void smCopyData(IntPtr dest, IntPtr len);
并最终调用它:
C#:
{
// create IntPtr for message
IntPtr msg_intptr = new IntPtr();
smCopyData(msg_intptr, (IntPtr)Marshal.SizeOf(typeof(smMsg)));
// create actual data struct
// smMsg is a struct referenced in both .dll & Unity script
smMsg data_msg = new smMsg();
// Set POINTER data to struct
Marshal.PtrToStructure(msg_intptr, data_msg);
}
我调试跟踪到smCopyData出现的错误,在日志中发现如下错误:
`VCRUNTIME140D.dll caused an Access Violation (0xc0000005) in module VCRUNTIME140D.dll at 0033:b4761c89.`
.dll 与其他函数一起工作,我能够成功连接到服务器,除了出现这个错误。
现在我不知道下一步该怎么做,因为我需要这个函数将数据从服务器复制到结构中。
我如何才能将内存从服务器 (mapBuffer) 复制到 C# 的参数变量中?
Reference to Marshal & IntPtr
Editor.log 堆栈跟踪
0x00007FFBB70A1C89 (VCRUNTIME140D) memcpy
0x00007FFBB72819D9 (SharedMemoryClientDLL) [l:\projects\google\chapstick\software\working\abner\misc proj\vs\sharedmemoryclientdll\sharedmemoryclientdll\smclibrary.cpp:151] smCopy
0x0000000012B65B29 (Mono JIT Code) (wrapper managed-to-native) SMCScript:smCopyData (intptr,intptr)
0x0000000012B65793 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:202] SMCScript:GetData ()
0x0000000012B62CA3 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:176] SMCScript:CheckForEvent ()
0x0000000010B69232 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:150] SMCScript:Update ()
0x00000000007D68E2 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007FFB9B5F41BF (mono) [c:\buildslave\mono-runtime-and-classlibs\build\mono\mini\mini.c:4937] mono_jit_runtime_invoke
0x00007FFB9B548435 (mono) [c:\buildslave\mono-runtime-and-classlibs\build\mono\metadata\object.c:2623] mono_runtime_invoke
0x000000014033E20F (Unity) scripting_method_invoke
您需要分配一个缓冲区并将其指针传递给函数。您只是传递了一个空指针,因此 cpp 函数试图写入地址 0,这会导致访问冲突异常。
var len = Marshal.SizeOf(typeof(smMsg));
IntPtr msg_intptr = Marshal.AllocHGlobal(len);
try {
// call the function, convert output to struct, etc...
}
finally {
Marshal.FreeHGlobal(msg_intptr);
}
我创建了一个用于 Unity5 C# 程序的 C++ .dll 库。
但是,当我 运行 来自 Unity 编辑器的程序并尝试调用 smCopy 时,Unity 崩溃并尝试发送错误报告;相反,我追踪到该错误是从 smCopy 发生的访问冲突错误。
.dll 库允许我连接到服务器并通过此函数将数据复制到给定参数中:
C++:
void DLL_API smCopy(const VOID *dest, SIZE_T len)
{
CopyMemory((PVOID)(dest), (PVOID)(mapBuffer), len);
}
在我的 Unity 脚本中,我导入函数:
C#:
[DllImport(DLL_NAME, EntryPoint = "smCopy")]
private static extern void smCopyData(IntPtr dest, IntPtr len);
并最终调用它:
C#:
{
// create IntPtr for message
IntPtr msg_intptr = new IntPtr();
smCopyData(msg_intptr, (IntPtr)Marshal.SizeOf(typeof(smMsg)));
// create actual data struct
// smMsg is a struct referenced in both .dll & Unity script
smMsg data_msg = new smMsg();
// Set POINTER data to struct
Marshal.PtrToStructure(msg_intptr, data_msg);
}
我调试跟踪到smCopyData出现的错误,在日志中发现如下错误:
`VCRUNTIME140D.dll caused an Access Violation (0xc0000005) in module VCRUNTIME140D.dll at 0033:b4761c89.`
.dll 与其他函数一起工作,我能够成功连接到服务器,除了出现这个错误。
现在我不知道下一步该怎么做,因为我需要这个函数将数据从服务器复制到结构中。
我如何才能将内存从服务器 (mapBuffer) 复制到 C# 的参数变量中?
Reference to Marshal & IntPtr
Editor.log 堆栈跟踪
0x00007FFBB70A1C89 (VCRUNTIME140D) memcpy
0x00007FFBB72819D9 (SharedMemoryClientDLL) [l:\projects\google\chapstick\software\working\abner\misc proj\vs\sharedmemoryclientdll\sharedmemoryclientdll\smclibrary.cpp:151] smCopy
0x0000000012B65B29 (Mono JIT Code) (wrapper managed-to-native) SMCScript:smCopyData (intptr,intptr)
0x0000000012B65793 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:202] SMCScript:GetData ()
0x0000000012B62CA3 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:176] SMCScript:CheckForEvent ()
0x0000000010B69232 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:150] SMCScript:Update ()
0x00000000007D68E2 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007FFB9B5F41BF (mono) [c:\buildslave\mono-runtime-and-classlibs\build\mono\mini\mini.c:4937] mono_jit_runtime_invoke
0x00007FFB9B548435 (mono) [c:\buildslave\mono-runtime-and-classlibs\build\mono\metadata\object.c:2623] mono_runtime_invoke
0x000000014033E20F (Unity) scripting_method_invoke
您需要分配一个缓冲区并将其指针传递给函数。您只是传递了一个空指针,因此 cpp 函数试图写入地址 0,这会导致访问冲突异常。
var len = Marshal.SizeOf(typeof(smMsg));
IntPtr msg_intptr = Marshal.AllocHGlobal(len);
try {
// call the function, convert output to struct, etc...
}
finally {
Marshal.FreeHGlobal(msg_intptr);
}