附加信息:试图读取或写入受保护的内存.这通常表明其他内存已损坏

本文关键字:内存 受保护 已损坏 其他 常表明 信息 读取 | 更新日期: 2023-09-27 18:15:49

我正在尝试将字节数组传递给c++ dll:

c++:

extern "C" __declspec(dllexport) char* myfunction(byte bytes[])
{
    char *byteschar = (char*)bytes;
    //do somethings with it
    return byteschar;
}
c#:

[DllImport("mydll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl
        ,CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string myfunction(byte[] bytes);

但是当我调用myfunction时我得到一个System.AccessViolationException

当我在没有调试器的情况下运行可执行文件时,它似乎工作良好

附加信息:试图读取或写入受保护的内存.这通常表明其他内存已损坏

如果您希望在c#中分配缓冲区并在c++中填充,则方法略有不同。

你应该分配一种"非托管"缓冲区,传递给DLL,然后转换结果并释放缓冲区。这在C中是完全相同的方式,但是从托管环境中调用。

你的c++代码应该是这样的:

extern "C" __declspec(dllexport) void myfunction(char* buffer, int length)
{
    //Fill buffer with something observing the maximum length of the buffer.
}
c#中DLL的签名应该是:
[DllImport("mydll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl
        ,CharSet = CharSet.Ansi)]
public static extern string myfunction(IntPtr buffer, Int32 length);
要从c#调用它,你应该这样做:
    IntPtr unmanagedBuffer = Marshal.AllocHGlobal(100);
    // Your Unmanaged Call
    myfunction(unmanagedBbuffer, 100);
    string yourString = Marshal.PtrToStringUni(unmanagedBuffer);
    Marshal.FreeHGlobal(unmanagedBuffer);

如果你不想在你的应用中出现内存泄漏,不要忘记调用FreeHGlobal。在"try/finally"子句中保护这个是很有趣的。

另一个观察是字符串的编码。Uni的意思是统一码。如果您使用其他字符串表示,请检查是否有等效的PtrToStringXXX函数。

应该是:

extern "C" __declspec(dllexport) char* myfunction(unsigned char * bytes)
{
    //do somethings with it
    return bytes;
}
相关文章: