http://www.web008.net

代码遇到的问题总结

不久前在开荒服务后台的时候,使用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,如若使用的是三十个人的c++版dll,必要把C#品种的编写翻译平台安装为x86,假设选拔的是61人的c++版dll,则设置为any cpu和x64都能够,这一个要求团结依照真实意况对应好就足以了。如若程序对内部存款和储蓄器的施用比较高,最棒将次第编写翻译为陆10个人,因为叁11人程序对单进程的内部存款和储蓄器大小有限量,经测验最大不超过2G。因为作者的主次刚开首使用的是叁10位的c++版dll,並且在运行时索要调用这一个dll加载非常多财富,加载完那么些能源进程占用的内部存款和储蓄器就大概快2G了,所以总会莫明其妙的崩掉,以致在加载的进程中就径直崩掉了,那时预知到是三10个人的标题,后来让同事将dll重新编写翻译为陆九人后就未有这几个题材了。能够透过dumpbin命令判断叁个dll是叁11个人依然陆九位,张开vs开拓人士命令提醒,输入:dumpbin /headers 你的dll路径,例如:dumpbin /headers d:test.dll,如下图所示:

图片 1

只假设33位dll,红框这里会来得 图片 2

此处有二个地点供给潜心,暗中认可asp.net项目在调节和测验时会运转在三15位下的iisexpress进程中,假令你的类型是陆拾贰个人的,那么须求在VS上将iisexpress配置为陆十二位情势,如下图所示:

图片 3

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

以此标题在运作时一时候会提醒dll加载不成事,那一个主题材料在不一致的微管理器上会有分歧的反映,有的存在这里个题目,有的就运转平常化。而小编本机就属高满堂常的,计划的服务器属于出难点的。出现这么些题目后,在确认代码不易后,小编用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个参数就不会截断了。

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

实际上还会有龙腾虎跃部分主题素材,到前天多少记不清了,就不敢贸然凭残余的那点回忆来描述了,以便变成不须要的误会。对于遇到的主题素材,有个别很明朗,有个别很遮掩,有个别须要稳重深入分析,有些须求在大气测量检验的地方下才会发觉,这里只想说一句:测量试验很珍视,职业需用心。

郑重声明:本文版权归美高梅163888所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。