从 c# 项目 System.AccessViolationException 调用 c++ char*

Posted

技术标签:

【中文标题】从 c# 项目 System.AccessViolationException 调用 c++ char*【英文标题】:calling c++ char* from c# project System.AccessViolationException 【发布时间】:2018-11-05 14:49:35 【问题描述】:

我试图从一个 c# 项目中调用一个 c++ 库方法,但没有取得多大成功。我总是遇到同样的错误。

System.AccessViolationException: 'Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.'

c++ 方法签名是这样的

int __stdcall getErrorMessage(int errorId, char *&errorMessage);

到目前为止,我已经尝试了所有组合,但似乎没有任何效果。

[DllImportAttribute("Lib.dll", EntryPoint = "getErrorMessage", 
CallingConvention = CallingConvention.StdCall)] 
public static extern int getErrorMessage(int errorId, ref StringBuilder errorMessage);

[DllImportAttribute("Lib.dll", EntryPoint = "getErrorMessage",
CallingConvention = CallingConvention.StdCall)] 
public static extern int getErrorMessage(int errorId, ref IntPtr errorMessage);


[DllImportAttribute("Lib.dll", EntryPoint = "getErrorMessage",
CallingConvention = CallingConvention.StdCall)] 
public static extern int getErrorMessage(int errorId, IntPtr errorMessage);

任何帮助将不胜感激。

编辑

我的称呼方式如下

var ptr = new IntPtr();

var ret = NativeMethods.getErrorMessage(number, ref ptr);

还有一个调用完成后释放内存

【问题讨论】:

请提供minimal reproducible example 那么 getErrorMessage 可能分配了一些内存并在 char*& 参数中返回指向它的指针?为了正确清理,您需要知道该内存是如何分配的。如果它不是互操作层支持的分配器之一(例如 CoTaskMemAlloc),我担心你不走运。当然,您始终可以使用 C++/CLI 编写包装器库。 还有另一种方法可以释放此调用分配的内存。我调用它的方式是 var ptr = new IntPtr(); var ret = NativeMethods.getErrorMessage(number, ref ptr); 你看到了吗? ***.com/questions/14816970/… ref IntPtr 是正确的,你是否传递了一个有效的数字是无法猜测的。假设您应该只在另一个函数指示失败时调用它,这可能是明智的。将一个小型 repro 项目发送给 C++ 代码的作者,以便他进行调试。 【参考方案1】:

获得IntPtr 后,您应该使用PtrToStringAutoPtrToStringAnsi 将其转换为string

【讨论】:

【参考方案2】:

它终于起作用了,正如 Hans Passant 所说,当我们尝试使用任意错误代码查询该方法时,问题就发生了。

工作代码。

var ptr = new IntPtr();

var ret = NativeMethods.getErrorMessage(code, ref ptr);

        if (ptr != IntPtr.Zero)
        
            message = Marshal.PtrToStringAnsi(ptr);
            NativeMethods.freePointer(ref ptr);
        

感谢您的帮助。

【讨论】:

以上是关于从 c# 项目 System.AccessViolationException 调用 c++ char*的主要内容,如果未能解决你的问题,请参考以下文章

使用 Powershell 或 C# 从 TFS 项目中删除用户

从 c# 项目 System.AccessViolationException 调用 c++ char*

如何将 .exe 从 C++ 项目复制到 C# 项目的输出目录?

如何从 c++ 项目中调用用 c# 创建的 dll 文件? [复制]

将项目从 C++ 转换为 C#

从 c# 调用 c++ 库