澳门至尊网站-首页

您的位置:澳门至尊网站 > 程序编程 > 代码遇到的问题总结

代码遇到的问题总结

2019-10-26 01:58

方今在支付服务后台的时候,使用c#调用了四个c++编写的dll,时期碰到了一文山会海的主题素材,经过生机勃勃番着力最后都相继解决了,在那做个总计,方便今后参照他事他说加以考查,毕竟这个难题也都以很普及的,重要有以下难点:

  • 项目对照难点
  • 内存释放难点
  • 本子难点(x86与x64)
  • 编写翻译难点(静态与动态)
  • 能源加载难点
  • 相当捕获与主题材料一定
  • vs实时调试难点

花色对照难点

c#调用c++方法时,首先要在类中定义一个与c++方法对应的表面方法,因为该措施是用C#言语定义的,那么自然要弄清楚C#花色与c++类型如何对应,不然会促成调用失利,关于那一个标题实际上不算什么难题,英特网有成百上千门类对照的稿子,都有很详细的应和列表,用的时候参谋一下就足以了。还是能够动用工具,自动根据c++方法签字生成对应的C# import方法签字,参谋P/Invoke Interop Assistant。但是有多少个难点大概要注意的,在x86格局下c#中的int对应c++中的int,而在x64模式下C#中的int是对应c++中的long,就这么贰个纤维的变量类型,在不经意间可能就能够产生c++代码出错。

再有多少个问题是:托管的 PInvoke 签名与非托管的目标签名不匹配澳门至尊网站,,可以在C#代码的不二诀要个性上助长CallingConvention.Cdecl。如下所示:

[DllImport("dllname.dll", CharSet = CharSet.Ansi, EntryPoint = "methodname", CallingConvention = CallingConvention.Cdecl)]

内部存款和储蓄器释放难题

是因为这些标题时常境遇,并且只要不可能一举成功的话鲜明不会再考虑动用该dll了,那是一个可用性的主题素材。所以作者在调用c++方法的时候,平常都会先批量跑生龙活虎边,通过日记记录下每调用三次艺术后,当前行程所侵占的内部存储器大小,那样在运维黄金年代段时间以往,就会很明亮的收看内存是或不是持续巩固,假诺是的话就须求和编写制定该dll的同事进行关联,给他俩提供测验数据,确认发生难题的来头。不时尽管C++中的方法开展了内部存款和储蓄器释放,况且在c++测验代码中意气风发度远非内部存款和储蓄器增加难题了,不过在C#中调用的时候内部存款和储蓄器如故会不停压实,该问题大概跟使用的场景有关,小编这里是因为调用了贰个再次回到char *连串的c++方法,小编直接用C#中的字符串类型的三个变量选择了,结果开掘内部存款和储蓄器总是自由不了,后来让同事把c++的措施校勘了大器晚成晃参数,然后在C#低价StringBuilder类型的变量作为参数传入c++方法中来接收该办法的结果,那样该内部存储器难点就解决了。

C#
// 在C#中声明与C++方法对应的dllimport方法
[DllImport("dllname.dll", CharSet = CharSet.Ansi, EntryPoint = "Handle", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CPPMethod(string content,StringBuilder result);

// 该变量用来接收c++方法的处理结果,作为传出参数传入c++方法,在构造的时候必须明确指定大小
// 如果不指定或者指定的大小不足,会导致c++方法出现空间分配不够的异常
StringBuilder resultSB = new StringBuilder(length);
string cppParam = "some content";
bool isSuccess = CPPMethod(cppParam,resultSB);  // CPPMethod是与C++方法对应的dllimport方法

C++ 
// C++中的DLL函数原型,即:C#中要调用的方法,此处不再返回char *类型的结果,而是将结果放到传出参数result中
extern "C" __declspec(dllexport) bool Handle(char* content, char* result);  // result为传出参数

局地时候内部存款和储蓄器难点是纯粹出于c++代码导致的,常常蒙受内部存款和储蓄器难题,小编会用c++的测量试验工程再跑三次,看看是或不是依然有该难点,假诺是表明真是c++的bug了,能够通报同事去校勘bug了。

内部存款和储蓄器难题不时并不会反映的不得了肯定,那必要大家更是周详的观看比赛日志并发掘变成难点的实在原因。作者事先碰到该地点的三个标题,刚初始内部存款和储蓄器上升的幅度十二分显著,经过一再与支出该dll的同事关系后,难题早就减轻的大致了,可是一大波测量试验后发掘内部存款和储蓄器照旧会有几许高升,就算幅度非常小,但第六感告诉本身当中必有蹊跷,那倘若上线跑个几天岂不是还得爆,后来自己把每一回调用c++方法后当前历程占用的内部存款和储蓄器输出到文件中,经过精心察看,发现绝超过半数文本(文件内容要传播c++方法中进行拍卖)都没难题,内部存储器都很平静,可是有非常的小片段文书在扩散c++方法后,会导致内部存款和储蓄器相比较此外文件有叁个显眼的增高,看来难点是现身在这里些文件中,随后把这几个文件单独放在一块儿张开巡回调用,内部存款和储蓄器一下子就大幅增强了,前边就绝不说了,难题理之当然解决了。由此,要保持记日志的良好习惯,哪怕是在测试工程中

本子难题(x86与x64)

本子不相配的话,在调度时会提示正在加载格式不正确的dll,假设采纳的是三14个人的c++版dll,供给把C#连串的编写翻译平台安装为x86,倘诺应用的是六二十个人的c++版dll,则设置为any cpu和x64都足以,这几个须求协和依据实际意况对应好就能够了。假诺程序对内部存储器的使用相比高,最棒将前后相继编译为62个人,因为叁14人程序对单进程的内部存储器大小有限量,经测验最大不抢先2G。因为作者的程序刚开首利用的是33人的c++版dll,并且在运营时索要调用那些dll加载超级多能源,加载完这一个财富进程占用的内部存款和储蓄器就大致快2G了,所以总会莫明其妙的崩掉,以至在加载的历程中就径直崩掉了,那时预言到是三十几个人的标题,后来让同事将dll重新编写翻译为六13位后就从未这些主题材料了。能够通过dumpbin命令推断叁个dll是30人依然陆12个人,张开vs开拓职员命令提醒,输入:dumpbin /headers 你的dll路径,例如:dumpbin /headers d:test.dll,如下图所示:

澳门至尊网站 1

风度翩翩旦是叁十六位dll,红框这里会来得 澳门至尊网站 2

这里有三个地点必要小心,默许asp.net项目在调治时会运营在39个人下的iisexpress进度中,即使你的项目是六15个人的,那么须求在VS准将iisexpress配置为六十五位形式,如下图所示:

澳门至尊网站 3

编写翻译难点(静态编写翻译与动态编写翻译)

以此标题在运维时不常候会提醒dll加载不成事,那个难点在分化的Computer上会有区别的反映,有的存在此个标题,有的就运转如常。而自己本机就属于常规的,陈设的服务器属于出难题的。现身这些主题材料后,在承认代码不易后,小编用depends.exe以此工具查看了须臾间导致难点的极度c++版的dll都依赖什么程序集,在出题指标机器上会提醒有大器晚成对信任的dll不设有,而这么些dll在运维如常的机器上是存在的。下图桃红框中的为有些机器上恐怕会贫乏的dll:

澳门至尊网站 4

如果缺乏相关dll,该条目的侧边会显得出一个香艳的问号。那么些主题材料能够动用静态编写翻译举行减轻,关于什么是静态编写翻译能够自动百度,综上说述便是将顺序所正视的dll编写翻译到程序聚集,那样尽管别的机器不设有这一个dll也能够健康运行了,静态编写翻译能够在vs的门类性质中张开设置

澳门至尊网站 5

默认是多线程 DLL(/MD),即:动态编译,这里改革为 多线程(/MT),即:静态编译。

刚刚的布局只好消除远远不够MSVCP120.DLL和MSVC智跑120.DLL那风姿浪漫类难题,对于缺少MFC相关的dll,还要经过上面包车型地铁配备:

澳门至尊网站 6

默认是使用标准Windows库,这里改为在静态库中使用MFC

财富加载难点(相对路线与相对路线,dll中又调用其余dll加载财富)

其生龙活虎标题绝相比较较隐讳,现身时不会抛出十二分,只可以通过c++方法再次回到的情事码来剖断方法试行是或不是成功,要不是在那地放了三个断点,刻意看了须臾间,可能就脱漏那个主题素材了。

境况是如此的:
本人在webservice中调用c++版dll中的贰个开首化方法,该方法会加载一些财富文件,小编在vs中调和试行的时候没难点,发表之后居然无法加载财富,貌似是路线难题,小编把能源文件放到w3wp.exe的根目录下倒是能够成功加载,放在别的目录中就这多少个,碰着这么些标题首先想到的可能是财富随处的目录权限非常不够导致iis不能正常加载,因为事先有个近似的标题正是那样,但此次将能源四处的目录修正为Everyone客户的一点一滴调整权限依然非常,何况该难题只现出在b/s项目中,c/s项目并未有这几个主题材料。何况该目录中寄存了累累财富文件,有一点个c++版的dll都亟待自此处加载,其余多少个都没难点,就那四个dll不行,看来不是权力的标题。此时又想是否相对路线的标题,这自个儿改成相对路线吧,结果难题还是,后来在技艺群里有个大牌说试试Directory.SetCurrentDirectory,赶紧修正代码,测量检验了刹那间真正好使了。代码如下:

// 保存当前工作目录
string currWorkPath = Directory.GetCurrentDirectory();
// 切换当前工作目录
Directory.SetCurrentDirectory(resourcePath);
// 初始化进行资源加载
Init(resourcePath);  // 这里要注意,使用了SetCurrentDirectory方法后,resourcePath要用相对路径
// 还原当前工作目录
Directory.SetCurrentDirectory(currWorkPath);

如注释所示,使用SetCurrentDirectory切换了当前专门的学业目录后,方法中所用的不二秘籍要改为相对路径,大器晚成起头自己用的是相对路径,居然依然不可能加载。

新生发觉了该难题的开始和结果,在动用的dll中又调用此外二个dll举办财富加载,大概那样会导致那多少个直接调用的dll现身路线问题,所以现身能源加载失利。

老大捕获与主题素材一定

有关那三个捕获,尽管在方式中加多了特色HandleProcessCorruptedStateExceptionsSecurityCritical但要么捕获不到c++中的相当,原因可能是c++在遭遇一些极度时会产生程序直接退出,那样在C#中就自然捕获不到了,所以依旧尽量确定保证c++代码的强健性。
如果在c#中调用了多少个c++版dll中的方法,因为临时捕获不到相当,很难通过符合规律情势找到标题标来头,c++方法中只要现身十分恐怕会一向导致进度退出了,这时候可以依附操作系统中的事件查看器来寻觅卓殊是源于哪个dll,同不时候在原来代码中注释掉那段调用该c++方法的代码,也许mock一个办法调用,保险该段代码未有差距常,然后再进行测量试验,假设无特别,那么只要解决了特别c++方法的标题就可以,若是还应该有特别那么正是其他dll的难题,然后能够编写测验代码单独测量检验曾经出难题的dll中的方法。异常捕获+事件查看器+日志能够帮衬开垦者发现前后相继的大多数难点与原因。

其余难题

1、0X1A截断全文的标题

那些是c++代码读取文件时恐怕会碰到的二个主题素材,纵然在调解有些难点的经过中发掘了那么些意况,但新兴经开荒dll的同事说难题的来由不是这一个,这里就仅此记录一下吧,ifstream in("test.txt",'b');这么丰硕第三个参数就不会截断了。

2、vs实时调节和测验变成iis进程一向守候的难点

一遍相遇这一个难题都以在下班后边世的,那时候也不知底什么来头,后来透过windbg看了风姿罗曼蒂克晃测验程序和w3wp进程的转储文件,通过!gle -all指令发掘各个线程都在伺机景况,如下图所示:

澳门至尊网站 7

iis进度也是那般,本以为是代码死锁了,但是透过!locks指令也没开采存任何极其(关于那几个主题材料,能够参照他事他说加以调查 动用死锁深入分析,那时多少懵,不清楚是什么导致了这种情景,后来发生意气风发件工作让自家弄理解了为什么,那是在快下班的时候,程序正好现身了多个极其(虽是格外,其实不会导致程序崩溃退出),那时服务器上弹出了二个vs实时调节和测量检验的提示窗口,笔者留神到iis的cpu使用率忽地就降为0,测验程序的调控台也出口了线程等待的音讯,联想到事先这些STATUS_WAIT_0的错误新闻以致貌似死锁的事态,作者感到到到恐怕是iis终止了颇负线程,在等候vs实时调试这些互动窗口的利落,由于平时都以在收工后才会开启测验程序来注明程序的平稳,所以当弹出这些互动窗口时,一贯不会有人去管理,线程不会直接这么等下去,最终测验程序就淡出了,iis也无能为力再持续管理央求了,那几个互动窗口也雷同消失了(为啥用平常,因为作者从不特意去注意,只是凭印象以为在此之前没见过),想到那本身点了豆蔻梢头晃“撤废调节和测量检验”,程序继续往下运作了,也不再阻塞了。所以在程序运转的时候,最佳关闭VS的实时调节和测验成效,防止变成不供给的题目。进入visual studio中,选取【工具】->【选项】,点击【调式】,在【实时】选项卡中把【本机】【脚本】【托管】八个对勾撤除掉就足以了。

澳门至尊网站 8

实际正是实时调节和测量检验窗口不见了,我们也足以通过系统事件来找到一些一望可知,如下图所示,只不过很难仅凭这些事件就剖断难点的原由,因为服务器上运营了三个w3wp实例,只可以说通过那几个情状增强部分经验了。

澳门至尊网站 9

骨子里还应该有生龙活虎对标题,到今天多少记不清了,就不敢贸然凭余留的那点记念来陈述了,以便形成无需的误解。对于蒙受的标题,有些很明显,有个别很隐讳,有个别须要精心深入分析,有个别须要在大量测量试验的情形下才会开采,这里只想说一句:测量试验很主要,专门的工作需用心。

本文由澳门至尊网站发布于程序编程,转载请注明出处:代码遇到的问题总结

关键词: