从 C# 模块调用 C++ 函数会引发随机崩溃

Posted

技术标签:

【中文标题】从 C# 模块调用 C++ 函数会引发随机崩溃【英文标题】:Invoke C++ function from C# module raises random crashes 【发布时间】:2019-09-30 09:49:21 【问题描述】:

我的 C# 模块必须与暴露一组函数的 C++ dll 通信,并且需要根据被调用函数返回的数据进行处理。

这是我的 C# 代码,其中调用了 C++ 函数 (Npr),

 [DllImport("CppModule.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Npr"), System.Security.SuppressUnmanagedCodeSecurity]
    public static extern IntPtr Npr([MarshalAs(UnmanagedType.LPWStr)]string moduleIDCur,
        [MarshalAs(UnmanagedType.LPWStr)]string mName,
        [MarshalAs(UnmanagedType.LPWStr)]string threadID,
        [MarshalAs(UnmanagedType.LPWStr)]string sessionID,
        [MarshalAs(UnmanagedType.LPWStr)]string reqID,
        [MarshalAs(UnmanagedType.LPWStr)]string siteID,
        [MarshalAs(UnmanagedType.LPWStr)]string siteName,
        [MarshalAs(UnmanagedType.LPWStr)]string nodeOrder,
        [MarshalAs(UnmanagedType.LPWStr)]string dateTime,
        [MarshalAs(UnmanagedType.LPWStr)]string rType,
        [MarshalAs(UnmanagedType.LPWStr)]string rCode,
        [MarshalAs(UnmanagedType.LPWStr)]string headStr,
        [MarshalAs(UnmanagedType.LPWStr)]string cookStr,
        [MarshalAs(UnmanagedType.LPWStr)]string userAgent,
        int flag);

...
IntPtr rets =  Npr(reqHttp.Url.PathAndQuery,rAddr,Thread.CurrentThread.ManagedThreadId.ToString(),sessionID,reqGUID,
                           siteID,siteName,nodeStr,DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.GetCultureInfo("en-US")),reqHttp.RequestType,
                          HttpContext.Current.Response.StatusCode.ToString(), headers, cookieStr, uAgent,
                           flag);             // Native Call from C#
...

在 CppModule.dll 中

EXTERN_C WCHAR* __cdecl Npr(WCHAR* testString,WCHAR* mname,WCHAR* threadID,WCHAR* sessionID,
                                         WCHAR* rID,WCHAR* siteID,WCHAR* siteName,WCHAR* nodeOrder,
                                         WCHAR* dateTime,WCHAR* rType,WCHAR* rCode,WCHAR* headStr,WCHAR* cookieStr,WCHAR* uAgent,int flag)
 ... ...  return wcharPtr;

这个 Npr 函数调用随机给出异常。异常消息为Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 在 C# 中 Npr 函数调用的行号。我更改了这个函数 Npr 最近返回了一个 WCHAR*,从那里随机崩溃不断发生。我是否缺少任何与互操作相关的编组或类似内容?

【问题讨论】:

你的 C++ 函数返回一个指针,但它指向什么?该功能在做什么?如果崩溃是在 C++ 函数中,我们需要看到它才能提供帮助。 您将WCHAR* 返回值编组为IntPtr 的具体原因是什么? 只是猜测...停止返回 wchar* 并执行以下操作: @Sel_va - 我在评论中向您展示了示例 :) 只需将其视为输出参数,而不是返回。返回指针时可能会出现一些问题。尤其是可能导致内存损坏问题的内存泄漏。 @AdamJachocki 请再次阅读您的评论,它不包含任何代码。 【参考方案1】:

通常在我的程序中,如果一个C++函数返回一个字符串,我更喜欢在参数中传递一个StringBuilder,然后修改它。

类似:

[DllImport("CppModule.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Npr"), System.Security.SuppressUnmanagedCodeSecurity]
public static extern void Npr(StringBuilder returnValue, [MarshalAs(UnmanagedType.LPWStr)]string moduleIDCur,
    [MarshalAs(UnmanagedType.LPWStr)]string mName,
    [MarshalAs(UnmanagedType.LPWStr)]string threadID,
    [MarshalAs(UnmanagedType.LPWStr)]string sessionID,
    [MarshalAs(UnmanagedType.LPWStr)]string reqID,
    [MarshalAs(UnmanagedType.LPWStr)]string siteID,
    [MarshalAs(UnmanagedType.LPWStr)]string siteName,
    [MarshalAs(UnmanagedType.LPWStr)]string nodeOrder,
    [MarshalAs(UnmanagedType.LPWStr)]string dateTime,
    [MarshalAs(UnmanagedType.LPWStr)]string rType,
    [MarshalAs(UnmanagedType.LPWStr)]string rCode,
    [MarshalAs(UnmanagedType.LPWStr)]string headStr,
    [MarshalAs(UnmanagedType.LPWStr)]string cookStr,
    [MarshalAs(UnmanagedType.LPWStr)]string userAgent,
    int flag);
...
Npr(returnValue, reqHttp.Url.PathAndQuery,rAddr,Thread.CurrentThread.ManagedThreadId.ToString(),sessionID,reqGUID,
                       siteID,siteName,nodeStr,DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.GetCultureInfo("en-US")),reqHttp.RequestType,
                      HttpContext.Current.Response.StatusCode.ToString(), headers, cookieStr, uAgent,
                       flag);

...

在 c++ 代码中:

EXTERN_C void __cdecl Npr(WCHAR * wcharPtr, WCHAR* testString,WCHAR* mname,WCHAR* threadID,WCHAR* sessionID, WCHAR* rID,WCHAR* siteID,WCHAR* siteName,WCHAR* nodeOrder, WCHAR* dateTime,WCHAR* rType,WCHAR* rCode,WCHAR* headStr,WCHAR* cookieStr,WCHAR* uAgent,int flag)
 ... ... 

【讨论】:

以上是关于从 C# 模块调用 C++ 函数会引发随机崩溃的主要内容,如果未能解决你的问题,请参考以下文章

C++:当我的应用程序在随机位置崩溃时从哪里开始?

当我从 C# 代码调用导入的 C++ 函数时,为啥会引发 AccessViolationException?

滚动表格视图时,iOS 应用程序随机崩溃,不确定如何处理引发的错误

如何随机调用函数unity c# [重复]

解决随机崩溃

从 C++ 到 C# 的 P/Invoking int[] 显示随机大数而不是原始数组成员