记一次被非托管代码支配的恐惧「C#对接企微会话存档SDK问题修复」
2022/9/4 1:25:22
本文主要是介绍记一次被非托管代码支配的恐惧「C#对接企微会话存档SDK问题修复」,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
序
这个问题是我目前在做企微服务商开发以来周期最长、最折磨人的一个问题了;
从3月开始着手排查问题(其实在开发之初就发现了该问题,迫于进度,就暂时搁置了),其中断断续续去尝试解决,并且没有企微对接人,只能社区咨询以及demo调试,加之期间需求不断,也就拖到了当下;
加之企微并没有提供C#对接SDK的demo,我开发起初也仅能根据Java的demo进行开发(此处埋下伏笔);
问题
在使用会话存档SDK(C++开发的SDK)拉取会话媒体文件(视频、文件、语音、图片)时,导致程序崩溃;后排查发现,仅当媒体文件大于512k时,也就是走分片拉取是时才会引发崩溃;且在本地调试时,可能成功,且成功后后续大多都成功;
排查
1、确定崩溃异常信息;崩溃后捕获到的信息为:double free,甚至使用了WinDbg;
2、排查异常点:涉及内存释放的有一下地方FreeSlice()
、FreeMediaData()
,再综合实际情况,是在拉取媒体文件时导致的,故可定位到该方法上;
3、定位具体代码行:经过具体调试,确定只有经过GetOutIndexBuf()
,再进行FreeMediaData()
才会崩溃;
解决
问题点是定位了,但是,哪里引起问题呢?这是一个最大的问题,当时我就蒙圈了;来来回回尝试了很多次,始终是没有解决:
- 从异步方法转为同步方法;
- 降级、升级 .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类型转换问题。传值,与接收返回值问题
这篇关于记一次被非托管代码支配的恐惧「C#对接企微会话存档SDK问题修复」的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-12-06使用Microsoft.Extensions.AI在.NET中生成嵌入向量
- 2024-11-18微软研究:RAG系统的四个层次提升理解与回答能力
- 2024-11-15C#中怎么从PEM格式的证书中提取公钥?-icode9专业技术文章分享
- 2024-11-14云架构设计——如何用diagrams.net绘制专业的AWS架构图?
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#