【问题标题】:Converting a function from Visual Basic 6.0 to C# is throwing AccessViolationException将函数从 Visual Basic 6.0 转换为 C# 会引发 AccessViolationException
【发布时间】:2009-11-10 04:47:22
【问题描述】:

我正在将 Visual Basic 6.0 的函数转换为:

Declare Function RequestOperation Lib "archivedll" (ByVal dth As Long, ByVal searchRequestBuf As String, ByVal buflen As Long, ByVal FieldNum As Long, ByVal OP As Long, ByVal value As String) As Long

在 C# 中,我将函数声明为:

[DllImport("archivedll")]
public static extern int RequestOperation(int dth ,StringBuilder searchRequestBuf, int bufferLen, int fieldNum, int op, string value);

从C#调用RequestOperation时,抛出异常:

[System.AccessViolationException] = {“试图读或写保护 记忆。这通常是一个迹象 其他内存已损坏。"}

我已经成功调用了很多类似这样的函数,但是只有这个函数抛出了异常。

【问题讨论】:

    标签: c# vb6 access-violation


    【解决方案1】:

    这个函数显然没有抛出AccessViolationException - 相反,它通过“尝试读取或写入受保护的内存”产生访问冲突错误。 .NET 正在将该错误转换为AccessViolationException

    您必须弄清楚它为什么“试图读取或写入受保护的内存”。特别是,您是否初始化了您传递给它的StringBuilder?请发布您用来调用此方法的代码。

    【讨论】:

    • 是的,我已经使用 Capicity = 4096 Vb6 代码调用 Dim bufSearchRequest As String * 4096 retCode = SearchRequestOperation(hDocumentType, bufSearchRequest, Len(bufSearchRequest), fieldIdx, queryType, stringQuery) 初始化 StringBuilder,这是 C#调用 StringBuilder searchRequest = new StringBuilder(4096); retCode = RequestOperation(hDocumentType, searchRequest, searchRequest.Capacity, index, queryType, query);
    • 正如 Eran 所说,错误显然正在发生,因为您将 StringBuilder 对象传递给期望字符串的函数。它们不可互换。
    • Eran 不正确。 DLL 通过 searchRequestBuf 参数返回一个字符串。因此必须使用 StringBuilder。仅当 DLL 不修改输入字符串时才能使用字符串。例如,请参见此处。 msdn.microsoft.com/en-us/library/ms235282(VS.80).aspx
    • @ThaiV 你能解释一下你为什么接受这个答案吗?初始化 StringBuffer 解决问题了吗?
    • @ThaiV:这个答案对你有帮助吗?
    【解决方案2】:

    我认为函数声明中的StringBuilder 与它有关。您应该只使用普通的String

    【讨论】:

    • StringBuilder参数类型用于[OutAttribute]
    • 我觉得没关系。然而,您没有理由使用 StringBuilder 作为参数,因为它假设 构建字符串 以优化性能,而不是作为数据容器传递。
    • -1 Eran,你错了。 DLL 通过 searchRequestBuf 参数返回一个字符串。因此必须使用 StringBuilder - 不能使用 String,因为 .NET 字符串是不可变的。参见例如 MSDN msdn.microsoft.com/en-us/library/ms235282(VS.80).aspx
    • 哇,这真的很奇怪......我想你只能期待微软的这种粗略的实现。我的意思是 - 它是一个字符串生成器,它构建字符串......它与通过 ref 传递数据有什么关系?!
    • .NET 的 P/Invoke 机制在托管代码和非托管代码之间封送数据。它将 [out] 字符串数据编组到 StringBuilder 就好了。在称其为“粗略”之前,您应该阅读 P/Invoke。
    【解决方案3】:
    /// Return Type: int
    ///dth: int
    ///searchRequestBuf: BSTR->OLECHAR*
    ///buflen: int
    ///FieldNum: int
    ///OP: int
    ///value: BSTR->OLECHAR*
    [System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="RequestOperation")]
    

    public static extern int RequestOperation(int dth, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.BStr)] 字符串 searchRequestBuf, int buflen, int FieldNum, int OP, [System.Runtime.InteropServices .MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.BStr)] 字符串值) ;

    【讨论】:

    • 在 VB6 Declare 语句中,ByVal 字符串被编组为指向 ANSI 字符串的指针,而不是 BSTR。如果你想这样写,两次都应该是System.Runtime.InteropServices.UnmanagedType.LPStr
    猜你喜欢
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多