ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

记一次被非托管代码支配的恐惧「C#对接企微会话存档SDK问题修复」

2022-09-03 00:01:20  阅读:175  来源: 互联网

标签:问题 IntPtr C# mediaData char GetOutIndexBuf 企微会 SDK


这个问题是我目前在做企微服务商开发以来周期最长、最折磨人的一个问题了;
从3月开始着手排查问题(其实在开发之初就发现了该问题,迫于进度,就暂时搁置了),其中断断续续去尝试解决,并且没有企微对接人,只能社区咨询以及demo调试,加之期间需求不断,也就拖到了当下;
加之企微并没有提供C#对接SDK的demo,我开发起初也仅能根据Java的demo进行开发(此处埋下伏笔);

问题

在使用会话存档SDK(C++开发的SDK)拉取会话媒体文件(视频、文件、语音、图片)时,导致程序崩溃;后排查发现,仅当媒体文件大于512k时,也就是走分片拉取是时才会引发崩溃;且在本地调试时,可能成功,且成功后后续大多都成功;

排查

1、确定崩溃异常信息;崩溃后捕获到的信息为:double free,甚至使用了WinDbg;
2、排查异常点:涉及内存释放的有一下地方FreeSlice()FreeMediaData(),再综合实际情况,是在拉取媒体文件时导致的,故可定位到该方法上;
3、定位具体代码行:经过具体调试,确定只有经过GetOutIndexBuf(),再进行FreeMediaData()才会崩溃;

解决

问题点是定位了,但是,哪里引起问题呢?这是一个最大的问题,当时我就蒙圈了;来来回回尝试了很多次,始终是没有解决:

  1. 从异步方法转为同步方法;
  2. 降级、升级 .NET 版本,甚至使用 Framework 4.8 版本;

最后,还是出动了我司架构师大佬帮忙,在我描述我排错过程以及最终错误定位后,展开了“诊断”;果不其然,架构师就是架构师,三两下给我治得服服帖帖;
话不多说,直接上代码:

// 存在问题代码
[DllImport(DllName)]
public static extern string GetOutIndexBuf(IntPtr mediaData);

// 调用
var outIndexBuf = FinanceAdapter.GetOutIndexBuf(mediaData);
// 调整后代码
[DllImport(DllName, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GetOutIndexBuf(IntPtr mediaData);

// 调用
var oibPtr = FinanceAdapter.GetOutIndexBuf(mediaData);
var outIndexBuf = Marshal.PtrToStringAnsi(oibPtr);

想必做 P/Invoke 开发的大佬看到这已经笑出的猪叫,这什么玩意?哈哈哈哈,我也是哭笑不得;

微软文档也说明了这一问题:互操作指南-字符串参数,以及相关文档:Passing Strings Between Managed and Unmanaged Code
也就是在我调用GetOutIndexBuf返回string后,导致了mediaData被销毁了,也就引发了后边进行释放内存的异常,进而导致崩溃;

且回头仔细一看c的案例,不难发现,实际在我们调用GetOutIndexBuf时返回的是char*,是指针变量,而我用string去接收,这哪能没错呀......

typedef struct MediaData {
    char* outindexbuf;
    int out_len;
    char* data;    
    int data_len;
    int is_finish;
} MediaData_t;

char* GetOutIndexBuf(MediaData_t* media_data);

不过,这得怪java (:(手动滑稽)

public native static String GetOutIndexBuf(long mediaData);

总结

至此,这个无从下手的问题得以解决,问题的产生根源还是自己太菜了以及不了解 P/Invoke ;解决该问题的过程也让我涨了不少知识,还简单的使用了WinDbg(这玩意是真的牛,前提得看得懂),收获颇丰;
目前C#版本的会话存档SDK对接也达到了可用的状态(至少目前对于我们的业务来说是没问题了),在此我们也提供了相关源码,相关.NETer也可以参考参考,少走些弯路;

源码地址:
wework-finance-sdk-csharp
相关文章:
1、C#与C++ dll 之间传递字符串string wchar_t* char* IntPtr
2、c#调用c++ dll const char* String类型转换问题。传值,与接收返回值问题

标签:问题,IntPtr,C#,mediaData,char,GetOutIndexBuf,企微会,SDK
来源: https://www.cnblogs.com/memoyu/p/16651735.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有