PInvoke受保护内存读写错误求助:C++ DLL返回时触发异常
解决PInvoke保护内存错误的问题
哥们,我帮你揪出这个错误的核心根源了,咱们一步步来搞定它:
问题本质
当C#的P/Invoke接收返回值为string时,默认会认为这块内存是通过CoTaskMemAlloc分配的——处理完字符串后,它会自动调用CoTaskMemFree去释放内存。但你的C代码用的是new char[]分配内存,这是C CRT的分配器,和C#默认期望的分配器完全不兼容。所以C#尝试释放不属于它管理的内存,直接触发了“保护内存”的错误。
你切换调用约定没用,因为内存管理不匹配才是真凶。
三种解决方案
方案一:让C++用C#兼容的内存分配器
修改你的C++代码,用CoTaskMemAlloc替代new char[],这样C#就能正确识别并释放内存:
#include <objbase.h> // 必须包含这个头文件才能使用CoTaskMemAlloc // 你的原有逻辑... ans += ";"; ans += rans; cout << "returning value 2" << endl; size_t strLen = ans.size() + 1; char* retval = (char*)CoTaskMemAlloc(strLen); strcpy_s(retval, strLen, ans.c_str()); return retval;
改完后,你的C#调用代码不用动就能正常工作。
方案二:让C#负责分配内存(更安全推荐)
这种方式完全避免跨语言内存管理冲突,让C#提前分配好缓冲区,传递给C++函数填充:
C++端修改函数:
// 加extern "C"避免C++名字改编 extern "C" __declspec(dllexport) void Stop_Record(char* buffer, int bufferSize) { ans += ";"; ans += rans; cout << "returning value 2" << endl; // 用strcpy_s确保不会缓冲区溢出 strcpy_s(buffer, bufferSize, ans.c_str()); }
C#端修改PInvoke声明和调用:
[DllImport("C:\\Users\\Boaz\\source\\repos\\Macro_Setter_DLL\\Debug\\Macro_Setter_DLL.dll", CallingConvention = CallingConvention.StdCall)] static extern void Stop_Record(StringBuilder buffer, int bufferSize); // 调用示例 StringBuilder resultBuffer = new StringBuilder(1024); // 按需调整缓冲区大小 Stop_Record(resultBuffer, resultBuffer.Capacity); string tmp = resultBuffer.ToString();
这个方案最安全,内存完全由调用方(C#)掌控,不会出现泄漏或释放错误。
方案三:手动管理内存(适合特殊场景)
如果不想改C的分配方式,可以返回IntPtr,在C#里手动处理字符串,最后调用C提供的释放函数清理内存:
C++端新增释放函数:
extern "C" __declspec(dllexport) void FreeRecordString(char* str) { delete[] str; // 和new char[]对应释放 }
C#端修改声明和调用:
[DllImport("你的DLL路径", CallingConvention = CallingConvention.StdCall)] static extern IntPtr Stop_Record(); [DllImport("你的DLL路径", CallingConvention = CallingConvention.StdCall)] static extern void FreeRecordString(IntPtr ptr); // 调用 IntPtr strPtr = Stop_Record(); string tmp = Marshal.PtrToStringAnsi(strPtr); FreeRecordString(strPtr); // 必须手动释放,否则会内存泄漏
总结
优先选方案二,其次是方案一,方案三尽量少用(容易忘释放导致泄漏)。跨语言调用最容易栽在内存管理上,核心就是要确保分配内存的方式和释放内存的方式完全匹配~
内容的提问来源于stack exchange,提问作者Monty6400
相关产品推荐
相关产品推荐

