代码蒙受的标题总括,Windbg使用表明书

By admin in 4858.com on 2019年4月8日

近日在开发服务后台的时候,使用c#调用了多少个c++编写的dll,时期遭遇了一密密麻麻的难题,经过1番奋力最后都相继化解了,在此做个总计,方便以后参考,究竟那一个题目也都以很普遍的,首要有以下难题:

近期在开发服务后台的时候,使用c#调用了多少个c++编写的dll,时期遇到了一体系的难题,经过壹番奋力最终都逐项化解了,在此做个小结,方便未来参考,毕竟那一个题目也都是很广阔的,重要有以下难点:

C#调用Java

将jar转换为dll
切切实实步骤 :下载3个 IKVM 配置好环境变量 具体操作如下
1、将已经编写翻译后的java中Class文件进行李包裹装;打包命令JA本田CR-V

  1. 那边
    java的持有类必须放在1个Package中,不要采纳缺省的包,C#会找不到类之间的调用(C#貎似不能够引用此外dll里的暗中认可namespace里边的剧情,所以java文件必须申明包,以便被转换到命名空间。其它,因为
    java中暗中认可访问权限的主意会被转换到internal方法,所以在java中务必将那一个主意显式地宣称为public),要求本人建,小编用的是eclipse,写完程序直接导出成jar文件。

其余将来以此本子好像不补助Java
图形界面,反正自身调节和测试时,壹旦new一个控件,C#就说此办法未被完毕怎么样的。

  1. 也得以选拔命令:jar cvf test.jar -C com/ .

里面test.jar为要转移的jar包;com/ .
为钦点的当前目录下的文件夹,该文件夹包蕴子文件夹及class文件;

2、到IKVM官方网址下载IKVM要求的机件
http://www.ikvm.net/

ikvmbin-0.44.0.5.zip

3、设置路径

解压ikvmbin-0.44.0.5.zip
,并将%IKVM_HOME%\bin添加到path中。此处的%IKVM_HOME%是指解压后ikvm的主目录。

肆、将java的jar包转换为.dll控件

运用的授命:ikvmc -out:IKVM.dll test.jar (整个操作那个是重点的。)

其间IKVM.dll为就要变化的.dll控件文件名;test.jar(尽量添加上文件的门径)为事前打包好的jar包文件。(写的时候尽量添加文件的门道名称,便于寻找生成后的dll文件

明日dll文件已经成功了,不过后边还有使用这几个dll在足够到C#品种中运转的时候或许会报错。那几个不当正是缺点和失误1些IKVMxxxx.dll文件,那么些文件都在ikvm-0.4陆.0.1\bin
文件下得以找到。

五、在C#品种中添加所需的控件

1、新建1个C#.NET项目,首先添加一下必须的DLLs (references中Add
reference,然后Browse找到dll)

%IKVM_HOME%\bin\IKVM.OpenJDK.Core.dll

%IKVM_HOME%\bin\IKVM.Runtime.dll

%IKVM_HOME%\bin\IKVM.Runtime.JNI.dll

②、添加已生成的.dll文件

将事先生成好的.dll文件加载到C#项目中

六、测试

在C#花色中选择java类,其方法同java。首先用using 包名,那样才能找到类

术语、缩略语

  • 类型对照难点
  • 内部存款和储蓄器释放难点
  • 本子难题(x八六与x6四)
  • 编写翻译难题(静态与动态)
  • 能源加载难点
  • 充足捕获与题材一定
  • vs实时调节和测试难点
  • 项目对照难点
  • 内存释放难点
  • 本子难题(x捌陆与x6四)
  • 编写翻译难点(静态与动态)
  • 能源加载难点
  • 那多少个捕获与题材一定
  • vs实时调节和测试难点

Java使用jna调用c#中的dll

壹、原理表达:
因为c#代码是托管到.net平台上的,所以java无法直接调用c#代码,于是引进C++中间件,c++项目得以安装项目为clr公共运营时,从而通过引用的章程调用c#相应措施。而jna是能够一向调用c++生成的dll的,于是大致流程就走通了。c++调用写好的c#dll,java再调用c++生成的dll中间件,差不多流程正是那样了,但是个中有无数坑,下边小编会细说。

贰、运行平台:

  • 系统:Windows 10 x64

  • 开发工具:Visual Studio
    二零一四/20一七(笔者台式机和集团电脑安装区别版本,笔者都有落到实处过)
    MyEclipse201四

  • SDK:jdk-x86、jdk-x6四(dll分为x八六和x64平台,和jdk的本子要相应,同一台电脑装两个版本的jdk比较烦,小编动用的是系统布置jdk33位调节和测试叁拾陆位dll,然后myeclipse自带60位jdk调节和测试陆拾3位dll)

三、准备工作:

4858.com ,一、首先准备上述运维平台,建议选取和体系位数壹致的jdk(安装vs、myeclipse或eclipse或sts);

2、下载jna.jar
:JNA下载
(下载jna-4.4.0.jar 和 jna-platform-4.4.0),也可以
本地下载

四、开始CODE

1. 生成c#DLL

(一)以管理人格局运营vs(项目事关到注册com组件,必须以管理员运维才能做到),新建c#项目

4858.com 1

(二)设置c#项目

率先,右键刚刚新建的Invoke项目,点击属性。

4858.com 2

继续设置项目性质。

4858.com 3

记得保存。

下一场新建必要被调用的CSharp类代码。那里大家新建壹些不难的办法,为了演示效果大家独家对int、string、bool实行操作。如图:

4858.com 4

下一场右键项目,点击生成。

4858.com 5

首先步,完毕,干得有滋有味。

2. 生成c++中间件

(①)新建c++项目并设置属性

4858.com 6

4858.com 7

4858.com 8

品类新建成功,右键项目,选拔属性。

4858.com 9

4858.com 10

image

(二)书写c++代码

添加cpp文件

4858.com 11

4858.com 12

编辑cpp文件

好了,c++和c#全部办事形成,右键生成。

4858.com 13

复制下dll生成文件全名,壹会儿java里面用。

五、编写java代码

壹. 新建java project
,注意选用和dll平台1致的jdk。然后将以前下载的多个jna的jar加载到花色里面,如图:

4858.com 14

2. 开始写java 代码

接下来大家运转:

4858.com 15

哦豁,报错了【无效的内部存款和储蓄器访问】,因为java找到了c++dll,不过没找到c#代码蒙受的标题总括,Windbg使用表明书。的dll,当中c++dll我们写的全体径名,能够一贯找到,那么c#的dll怎么找呢。答案是将c#的dll复制到jdk的bin目录下,jvm就能找到了。

如图大家将Invoke.dll复制到jdk的bin目录下:

4858.com 16

下一场再运营:

4858.com 17

nice!对于常用类型中的int、string、boolean都足以万事大吉传递了,事实上别的类型的也能够落成,只要依据分歧语言之间的连串对应关系就足以了,具体的品类涉及足以百度。

陆、注意事项

1. java报错:Exception in thread “main” java.lang.Error: Invalid
memory access

或然原因:

  • c#dll未有复制到jdk的bin目录;

  • java和c++之间数据类型不对应;

2. java报错:Exception in thread “main”
java.lang.UnsatisfiedLinkError: Unable to load library ‘D:\vs
workplace\X86InvokeTest\Release\X86CPPDlls’: Native library
(win32-x86/D:\vs workplace\X86InvokeTest\Release\X86CPPDlls.dll) not
found in resource path
([file:/G:/My%20Eclipse%20workplace/InvokeCSharpX86Test/bin/,
file:/G:/My%20Eclipse%20workplace/InvokeCSharpX86Test/Lib/jna-4.4.0.jar,
file:/G:/My%20Eclipse%20workplace/InvokeCSharpX86Test/Lib/jna-platform-4.4.0.jar])

或是原因:

  • c++dll路径不科学,建议做test时用绝对路径,这样您在c++项目编写翻译过后不要拷贝便得以在java程序里面一贯调用;

  • jdk的阳台和c++项目标阳台不匹配,jdk是3几人那么c++dll一定也是3一个人的,6几人也一如既往;

三.
windows612位下编写翻译的三十一个人dll测试失利,一时半刻不精通是还是不是陆十二位系统的来头,由于我电脑虚拟机未有装上,就从未有过去3三人系统上测试了。

windbg 

品类对照难题

c#调用c++方法时,首先要在类中定义2个与c++方法对应的外部方法,因为该格局是用C#言语定义的,那么势供给搞清楚C#种类与c++类型怎样对应,不然会造成调用失利,关于这些难题莫过于不算什么难点,网上有那三个类别对照的文章,都有很详细的应和列表,用的时候参考一下就能够了。还足以采取工具,自动依照c++方法签名生成对应的C#
import方法签名,参考P/Invoke Interop
Assistant。不过有八个难题要么要专注的,在x八陆形式下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)]

种类对照难题

c#调用c++方法时,首先要在类中定义2个与c++方法对应的外表方法,因为该措施是用C#语言定义的,那么自然要弄清楚C#花色与c++类型如何对应,不然会促成调用退步,关于这么些题目实际上不算什么难题,网上有好多类型对照的稿子,都有很详细的照应列表,用的时候参考一下就足以了。还足以动用工具,自动依据c++方法签名生成对应的C#
import方法签名,参考P/Invoke Interop
Assistant。不过有二个标题依然要专注的,在x8六形式下c#中的int对应c++中的int,而在x64模式下C#中的int是对应c++中的long,就像是此三个微细的变量类型,在不经意间只怕就会招致c++代码出错。

再有2个难点是:托管的 PInvoke 签名与非托管的目标签名不匹配,可以在C#代码的办法特性上助长CallingConvention.Cdecl。如下所示:

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

windows平台下,强大的用户态和内核态调节和测试工具。

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

出于这些题材日常蒙受,并且只要不可能化解的话肯定不会再思念接纳该dll了,那是四个可用性的难题。所以本人在调用c++方法的时候,平时都会先批量跑1边,通过日记记录下每调用三遍艺术后,当前进度所占用的内部存储器大小,那样在运行一段时间现在,就能很了然的观望内部存储器是还是不是持续升高,固然是的话就需求和编排该dll的同事实行联系,给他们提供测试数据,确认产生难点的原由。有时即便C++中的方法开始展览了内存释放,并且在c++测试代码中早就远非内存增进难题了,然则在C#中调用的时候内部存款和储蓄器照旧会没完没了抓好,该难点也许跟使用的情景有关,笔者那边是因为调用了3个回去char
*品类的c++方法,作者直接用C#中的字符串类型的3个变量接收了,结果发现内部存款和储蓄器总是自由不了,后来让同事把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为传出参数

1些时候内存难点是纯粹出于c++代码导致的,壹般境遇内部存款和储蓄器难题,作者会用c++的测试工程再跑一回,看看是还是不是仍有该难点,即便是表明真是c++的bug了,能够通报同事去修改bug了。

内部存款和储蓄器难点偶尔并不会体现的尤其显著,这亟需大家更为密切的观看比赛日志并发现导致难点的实在原因。小编在此之前境遇该地点的多个标题,刚初步内部存款和储蓄器上涨幅度十一分鲜明,经过再③与开支该dll的同事关系后,难点已经消除的大约了,但是多量测试后意识内部存款和储蓄器照旧会有几许高涨,纵然幅度不大,但第伍感告诉自身在那之中必有蹊跷,这假诺上线跑个几天岂不是还得爆,后来自个儿把每贰次调用c++方法后当前进度占用的内部存款和储蓄器输出到文件中,经过精心察看,发现绝大多数文书(文件内容要传播c++方法中展开始拍片卖)都没难点,内部存款和储蓄器都很平静,不过有不大片段文书在流传c++方法后,会促成内部存储器相比其余文件有二个令人注指标增加,看来难点是出现在这么些文件中,随后把这一个文件单独放在1块儿展开巡回调用,内部存款和储蓄器一下子就大幅度增强了,前边就毫无说了,难题理所当然消除了。由此,要保持记日志的良好习惯,哪怕是在测试工程中

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

鉴于这几个题目时常遭受,并且只要不可能缓解的话肯定不会再考虑选拔该dll了,那是3个可用性的题材。所以自身在调用c++方法的时候,平时都会先批量跑壹边,通过日记记录下每调用三次艺术后,当前历程所占有的内存大小,那样在运营一段时间以往,就能很清楚的观察内部存款和储蓄器是不是持续抓实,若是是的话就须求和编辑该dll的同事实行联络,给她们提供测试数据,确认爆发难点的来由。有时即便C++中的方法实行了内部存款和储蓄器释放,并且在c++测试代码中一度远非内部存款和储蓄器增长难点了,不过在C#中调用的时候内部存款和储蓄器依旧会持续增强,该难点或许跟使用的光景有关,作者那里是因为调用了三个赶回char
*项指标c++方法,作者向来用C#中的字符串类型的2个变量接收了,结果发现内部存款和储蓄器总是自由不了,后来让同事把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++代码导致的,1般碰着内部存款和储蓄器难点,作者会用c++的测试工程再跑3回,看看是不是仍有该难题,假诺是注解真是c++的bug了,能够公告同事去修改bug了。

内存难点偶尔并不会反映的要命斐然,那需求大家越来越细致的观测日志并发现造成难点的确实原因。我事先碰到该地方的3个题材,刚发轫内部存款和储蓄器上涨幅度10分强烈,经过反复与开发该dll的同事关系后,难题1度缓解的几近了,不过大批量测试后发觉内部存款和储蓄器依旧会有1些高涨,即便大幅度一点都不大,但第5感告诉自个儿在这之中必有好奇,那借使上线跑个几天岂不是还得爆,后来自小编把每2次调用c++方法后当前进程占用的内部存款和储蓄器输出到文件中,经过细心调查,发现绝大多数文件(文件内容要传播c++方法中开始展览处理)都没难点,内部存款和储蓄器都很平稳,不过有不大一些文本在扩散c++方法后,会招致内部存款和储蓄器相比其它文件有三个眼看的增进,看来难点是出新在这一个文件中,随后把这么些文件单独放在1起进行巡回调用,内部存款和储蓄器一下子就急剧升高了,前边就绝不说了,问题自然化解了。因而,要保持记日志的良好习惯,哪怕是在测试工程中

dmp

本子难点(x8六与x6四)

本子不相配的话,在调节时会提醒正在加载格式不正确的dll,假如采纳的是30个人的c++版dll,须要把C#连串的编写翻译平台安装为x八六,若是应用的是陆11位的c++版dll,则设置为any
cpu和x6四都能够,那几个需求协调依据实际意况对应好就能够了。假使程序对内部存款和储蓄器的运用相比高,最佳将先后编写翻译为6拾伍位,因为33个人程序对单进度的内部存款和储蓄器大小有限量,经测试最大不超过贰G。因为小编的程序刚起始利用的是三九个人的c++版dll,并且在运维时索要调用那些dll加载很多资源,加载完那几个能源进度占用的内部存款和储蓄器就差不多快二G了,所以总会莫名其妙的崩掉,甚至在加载的历程中就直接崩掉了,当时预见到是32人的标题,后来让同事将dll重新编写翻译为610人后就从不那些题材了。能够由此dumpbin命令判断三个dll是32人照旧陆拾二人,打开vs开发职员命令提示,输入:dumpbin /headers 你的dll路径,例如:dumpbin /headers d:\test.dll,如下图所示:

4858.com 18

假定是三十七人dll,红框那里会显得
4858.com 19

那里有一个地点必要小心,私下认可asp.net项目在调节时会运维在三15人下的iisexpress进程中,就算您的花色是陆十几个人的,那么需求在VS军长iisexpress配置为陆10个人格局,如下图所示:

4858.com 20

本子难题(x8六与x6四)

本子不协作的话,在调节时会提示正在加载格式不正确的dll,借使选拔的是33个人的c++版dll,必要把C#项目标编写翻译平台安装为x86,如若运用的是6几人的c++版dll,则设置为any
cpu和x6四都足以,这一个供给协调依据实际境况对应好就可以了。要是程序对内部存款和储蓄器的选拔相比较高,最棒将先后编写翻译为陆14个人,因为3三个人程序对单进度的内部存款和储蓄器大小有限制,经测试最大不超越二G。因为自个儿的先后刚发轫选择的是30个人的c++版dll,并且在运维时供给调用这一个dll加载很多能源,加载完这一个能源进度占用的内部存款和储蓄器就基本上快二G了,所以总会不可捉摸的崩掉,甚至在加载的历程中就直接崩掉了,当时预感到是三拾贰人的标题,后来让同事将dll重新编写翻译为陆14位后就一贯不那些难点了。能够经过dumpbin命令判断二个dll是30位照旧6二十一人,打开vs开发人士命令提示,输入:dumpbin /headers 你的dll路径,例如:dumpbin /headers d:\test.dll,如下图所示:

4858.com 21

假定是三9位dll,红框那里会突显
4858.com 22

此地有2个地方须要留意,私下认可asp.net项目在调节时会运维在33个人下的iisexpress进度中,假若您的项目是陆十一人的,那么须要在VS大校iisexpress配置为陆11位格局,如下图所示:

4858.com 23

内部存款和储蓄器影象文件,壹般是系统错误发生的文书。

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

那个题材在运营时有时候会唤醒dll加载不成事,那几个标题在不一致的微处理器上会有例外的显示,有的存在那些题材,有的就运转不荒谬。而本身本机就属周振天常的,布置的服务器属于出题指标。出现这些难题后,在肯定代码不易后,作者用depends.exe本条工具查看了一下导致难题的百般c++版的dll都依靠什么程序集,在出难题的机械上会提醒有部分借助的dll不存在,而这个dll在运营不奇怪的机械上是存在的。下图铁红框中的为一些机器上可能会缺少的dll:

4858.com 24

壹经贫乏相关dll,该条指标左侧会来得出贰个风骚的问号。这些标题得以采纳静态编写翻译实行缓解,关于怎么着是静态编写翻译能够自行百度,同理可得就是将次第所依靠的dll编写翻译到程序集中,那样就是别的机器不设有那几个dll也足以符合规律运作了,静态编写翻译能够在vs的品种性质中进行设置

4858.com 25

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

刚才的布署只可以化解不够MSVCP120.DLL和MSVC奔驰G级120.DLL那1类标题,对于缺少MFC相关的dll,还要通过上边包车型客车安排:

4858.com 26

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

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

其一难题在运作时有时候会唤起dll加载不成功,这些题材在不相同的微型计算机上会有两样的反映,有的存在那些难题,有的就运转平常化。而我本机就属于常规的,安顿的服务器属于出问题的。出现那几个标题后,在确认代码不易后,笔者用depends.exe那几个工具查看了1晃造成难点的13分c++版的dll都凭借什么程序集,在出题指标机器上会提示有1对凭借的dll不设有,而这一个dll在运维符合规律化的机器上是存在的。下图土黑框中的为某个机器上恐怕会缺乏的dll:

4858.com 27

只要贫乏相关dll,该条款的右侧会来得出八个艳情的问号。这么些题材得以运用静态编写翻译举办消除,关于什么是静态编写翻译能够活动百度,可想而知正是将顺序所依靠的dll编写翻译到程序集中,那样固然别的机器不存在那几个dll也能够平常运维了,静态编写翻译能够在vs的门类性质中开始展览安装

4858.com 28

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

刚刚的配置只可以消除不够MSVCP120.DLL和MSVC奥迪Q3120.DLL那一类标题,对于贫乏MFC相关的dll,还要经过上面包车型地铁布署:

4858.com 29

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

Pdb

能源加载难点(绝对路径与相对路径,dll中又调用别的dll加载能源)

其1题材绝比较较隐蔽,出现时不会抛出特别,只好通过c++方法重返的情事码来判断方式执行是不是成功,要不是在那里放了3个断点,特意看了须臾间,恐怕就遗漏这几个难题了。

气象是那样的:
自笔者在webservice中调用c++版dll中的叁个开端化方法,该方法会加载一些能源文件,笔者在vs中调剂执行的时候没难点,发布之后居然无法加载财富,貌似是路线难点,作者把财富文件放到w三wp.exe的根目录下倒是能够成功加载,放在其余目录中就卓殊,蒙受这么些难题首先想到的恐怕是能源随处的目录权限不够导致iis无法平常加载,因为事先有个1律的难点正是那般,但本次将财富四处的目录更改为伊夫ryone用户的完全控制权限依然越发,并且该难题只出现在b/s项目中,c/s项目未有这一个题材。并且该目录中存放了成都百货上千财富文件,有某个个c++版的dll都亟需从这边加载,其余多少个都没难题,就那2个dll不行,看来不是权力的题目。这时候又想是否相对路径的标题,那自个儿改成相对路径吧,结果难点照旧,后来在技术群里有个大拿说试试Directory.SetCurrentDirectory,赶紧修改代码,测试了须臾间的确好使了。代码如下:

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

如注释所示,使用SetCurrentDirectory切换了当前工作目录后,方法中所用的门路要改为绝对路径,壹起头小编用的是绝对路径,居然依然不能够加载。

新兴发觉了该难题的原因,在应用的dll中又调用其余多个dll举办能源加载,或者这么会造成那多少个直接调用的dll出现路径难点,所以出现财富加载失败。

能源加载难点(相对路径与相对路径,dll中又调用其余dll加载能源)

这一个标题相比较较隐蔽,现身时不会抛出尤其,只好通过c++方法再次回到的景况码来判断格局执行是还是不是中标,要不是在此间放了3个断点,特意看了壹晃,也许就遗漏那个题材了。

此情此景是这样的:
本人在webservice中调用c++版dll中的三个初阶化方法,该方法会加载一些能源文件,作者在vs中调剂执行的时候没难点,宣布之后居然不也许加载财富,貌似是路径难点,小编把财富文件放到w三wp.exe的根目录下倒是能够成功加载,放在其余目录中就那么些,遭受这些标题首先想到的可能是财富四处的目录权限不够导致iis无法不荒谬加载,因为事先有个相同的题材正是如此,但此次将资源随地的目录更改为伊芙ryone用户的完全控制权限依旧10分,并且该难点只现出在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中的方法。异常捕获+事件查看器+日志可以协理开发者发现先后的绝超越2/四题目与原因。

丰硕捕获与难点一定

至于那些捕获,纵然在艺术中添加了特征HandleProcessCorruptedStateExceptionsSecurityCritical但要么捕获不到c++中的相当,原因大概是c++在碰到1些极度时会造成程序直接退出,这样在C#中就自然捕获不到了,所以依旧尽量确定保障c++代码的健壮性。
如果在c#中调用了七个c++版dll中的方法,因为有时候捕获不到十分,很难通过正规方法找到题目标缘故,c++方法中要是出现格外或者会向来促成进程退出了,那时可以依靠操作系统中的事件查看器来找出万分是缘于哪个dll,同时在原始代码中注释掉那段调用该c++方法的代码,可能mock二个格局调用,保障该段代码无充裕,然后再实行测试,如果无差距常,那么只要化解了老大c++方法的标题即可,假诺还有万分那么正是任何dll的题材,然后能够编写制定测试代码单独测试曾经出题目标dll中的方法。异常捕获+事件查看器+日志能够支持开发者发现先后的超越1/2题材与原因。

Symbol

任何题材

其余标题

标记文件(Symbol
Files)是一个多少消息文件,它涵盖了应用程序二进制文件(比如:EXE、DLL等)调节和测试音信

一、0X一A截断全文的难题

那个是c++代码读取文件时大概会遇见的1个题目,纵然在调节和测试有个别难点的历程中窥见了这么些意况,但后来经开发dll的同事说难点的原故不是其一,那里就仅此记录一下吗,ifstream in("test.txt",'b');这么丰裕首个参数就不会截断了。

1、0X1A截断全文的标题

以此是c++代码读取文件时或许会遭遇的三个题材,即使在调节和测试有些难题的经过中发现了这几个情景,但新兴经开发dll的同事说难题的原由不是那一个,那里就仅此记录一下吧,ifstream in("test.txt",'b');如此那般充分第二个参数就不会截断了。


二、vs实时调节和测试造成iis进度一直等候的标题

四回相见那几个标题都以在下班后出现的,当时也不知情怎样来头,后来经过windbg看了1晃测试程序和w3wp进度的转储文件,通过!gle -all一声令下发现每种线程都在守候情形,如下图所示:

4858.com 30

iis进度也是如此,本以为是代码死锁了,不过通过!locks一声令下也没发现有其它分外(关于那些题材,能够参考
使用死锁分析,当时有点懵,不晓得是怎么样导致了这种景象,后来时有发生一件业务让本人弄精晓了为何,那是在快下班的时候,程序正好出现了3个万分(虽是极度,其实不会造成程序崩溃退出),那时服务器上弹出了1个vs实时调节和测试的提示窗口,小编注意到iis的cpu使用率突然就降为0,测试程序的控制台也出口了线程等待的音讯,联想到前边这一个STATUS_WAIT_0的错误信息以及貌似死锁的气象,作者倍感到恐怕是iis终止了拥无线程,在等待vs实时调节和测试这一个互动窗口的停止,由于日常都以在下班后才会开启测试程序来表达程序的喜笑颜开,所以当弹出这些互动窗口时,一向不会有人去处理,线程不会平素如此等下去,最后测试程序就退出了,iis也不或者再持续处理请求了,那几个互动窗口也诚如消失了(为何用一般,因为自个儿并未有特意去留意,只是凭影像觉得从前没见过),想到这自个儿点了一下“废除调节和测试”,程序继续往下运维了,也不再阻塞了。所以在程序运维的时候,最好关闭VS的实时调节和测试功用,防止导致不须要的难点。进入visual
studio中,选拔【工具】->【选项】,点击【调式】,在【实时】选项卡中把【本机】【脚本】【托管】多个对勾撤销掉就足以了。

4858.com 31

实质上就是实时调节和测试窗口不见了,我们也足以透过系统事件来找到1些一望可知,如下图所示,只可是很难仅凭那个事件就判断难点的原因,因为服务器上运营了八个w三wp实例,只可以说通过这么些情形进步部分经验了。

4858.com 32

实则还有部分标题,到近年来有点记不清了,就不敢贸然凭残存的那一点纪念来叙述了,以便造成不需要的误会。对于境遇的标题,有个别很鲜明,有个别很隐蔽,有个别必要细致分析,有个别要求在多量测试的景观下才会发现,那里只想说一句:测试很重大,工作需用心。

2、vs实时调节和测试造成iis进度平昔等候的题材

三遍相遇这一个标题都以在下班后出现的,当时也不明白怎么样来头,后来透过windbg看了1晃测试程序和w三wp进程的转储文件,通过!gle -all一声令下发现每种线程都在等候情形,如下图所示:

4858.com 33

iis进度也是如此,本以为是代码死锁了,不过通过!locks一声令下也没觉察有其它非常(关于这么些标题,能够参考
使用死锁分析,当时某个懵,不知情是怎样导致了那种景观,后来时有产生1件工作让本身弄精通了为啥,那是在快下班的时候,程序正好现身了3个10分(虽是十分,其实不会促成程序崩溃退出),那时服务器上弹出了1个vs实时调节和测试的晋升窗口,小编留心到iis的cpu使用率突然就降为0,测试程序的控制台也出口了线程等待的音信,联想到事先这一个STATUS_WAIT_0的错误音信以及貌似死锁的情景,笔者感觉到或许是iis终止了独具线程,在伺机vs实时调节和测试那么些互动窗口的收尾,由于平常都以在收工后才会张开测试程序来证实程序的安澜,所以当弹出这一个互动窗口时,一向不会有人去处理,线程不会直接这么等下去,最终测试程序就淡出了,iis也无力回天再持续处理请求了,这些互动窗口也相似消失了(为何用1般,因为本人从未尤其去注意,只是凭印象觉得在此之前没见过),想到那自个儿点了眨眼间间“裁撤调节和测试”,程序继续往下运转了,也不再阻塞了。所以在程序运营的时候,最佳关闭VS的实时调节和测试功用,防止导致不需要的题材。进入visual
studio中,采取【工具】->【选项】,点击【调式】,在【实时】选项卡中把【本机】【脚本】【托管】四个对勾裁撤掉就能够了。

4858.com 34

实际上即便实时调节和测试窗口不见了,大家也得以经过系统事件来找到壹些一望可知,如下图所示,只然而很难仅凭这么些事件就判断难点的因由,因为服务器上运维了七个w三wp实例,只好说经过这一个地方抓好部分经验了。

4858.com 35

事实上还有部分题材,到以后稍微记不清了,就不敢贸然凭残存的那一点回忆来讲述了,以便造成不须要的误会。对于碰到的题材,有些很明朗,有个别很隐蔽,有个别供给仔细分析,有个别须要在大气测试的场地下才会意识,这里只想说一句:测试很要紧,工作需用心。

概述

Windbg是Windows平台下强大的工具。相比较于Visual
Studio,它是一个轻量级的调剂工具,所谓轻量级指的是它的安装文件大小较小,可是其调节功用,却比VS更为强劲。它的其它3个用场是足以用来分析dump数据,仍是能够调剂进度死锁之类的。调节和测试成效,类似于Visual
Studio,还协理命令形式。该文书档案只适用于VC++,而C#的还需求卓殊开始展览部分布局,原理大概相同。

Windbg只是3个工具,要控制当中央的行使方法,和调剂命令,在实践中不断完善本身的调节手段。同时能够参考一下师父们的文献《Windows用户态程序高效排错》,《Windows高级调节和测试》,《软件调节和测试》


下载

Windbg使用十一分普遍,网上分外多的下载版本,而且文书档案也正如多,能够到CSDN恐怕其余网址下载,援救雾灰包运营。


配置

Windbg在选用前,供给开始展览布局。

壹.壹环境变量

壹、添加环境变量:_NT_SYMBOL_PATH

二、环境变量值:

C:\MyCodesSymbols;SRV*C:\MyLocalSymbols*

4858.com 36

环境变量配置

3、根据环境变量值,在C盘下新建文件夹:MyCodesSymbols,MyLocalSymbols那多个文本夹首要存放在windows的记号文件,也正是系统暗中同意的部分pdb文件,那一个文件不是系统自带的,必要配置好链接,第三回调节和测试的时候windbg默许下载供给的缺点和失误的symbol文件。

4858.com 37

pdb 下载的文本


Windbg工具配置

标记配置Symbol File Path

C:\MyCodesSymbols;SRV*C:\MyLocalSymbols*

4858.com 38

标记配置

源码路径配置Source File Path

工具不会智能定位到对应的源码,所以要布局你的源码工程的途径,是工程文件(例如那种格式的文书:*.vcxproj)所在的门道。

4858.com 39

源码配置一

4858.com 40

源码地方


编写翻译器配置

支撑VC6以上的Visual Studio编写翻译器,设置相关的天性

明确命令禁止优化项:

4858.com 41

取缔优化项一

4858.com 42

禁绝优化项二

转变程序数据库文件

4858.com 43

pdb 文件


使用

工具进行利用前安插后,能够实行工作了。那里介绍绑定进度展开调剂的操作步骤。


绑定进程

在意,进度要先运营再展开绑定设置,因为Attach to
Process窗口不会像职责管理器一样实时刷新进度。选中进度名称,点击Ok确认。

4858.com 44

绑定过程


调试

绑定进度后,能够在命令窗口输入g字母命令,然后回车。也许用快捷键F5。即可在调节中运转进程了。注意:要求pdb文件,和exe或dll放在一块儿,或许上文提到的把pdb文件放在C:\MyCodesSymbols目录。因为调节和测试音信都以依照pdb的公文时间戳进行稳定历史文件的,所以在公告版本后,最棒备份一下代码和文书。不然版本发出去了,原生源码进行编写翻译了,pdb不平等了,源码被涂改了,那么抓取到的*.dmp内部存款和储蓄器影像就无法确切地调节和测试。

次第被windbg绑定后,F五运作,以往能够不荒谬操作软件了。那时候软件有分外,命令窗口会打字与印刷相关的要命命令,如下图:

Access violation–code c0000005 (first chance)

4858.com 45

调试

那种是金榜题名的内部存款和储蓄器禁止访问万分。输入小写字母k命令,即可打字与印刷堆栈。左窗口也是应和的源码,像vs那样调节和测试。工具栏上有很多调剂窗口能够展示出来:

4858.com 46

调节工具栏

如局部变量数据彰显窗口:Locals

4858.com 47

变量突显窗口


命令

而外主导的可视化调试之外,windbg扶助命令进行任何的木本调节和测试,能够依照实际须求进行利用,上面简单介绍常用的命令:

一、查看版本音讯:version、vertarget。

二、查看模块消息:lm、!dlls、!lmvi等。

三、调用栈:用k命令展现调用栈,用.frames命令切换栈帧。

4、内部存款和储蓄器操作:读内部存款和储蓄器用d命令,写内部存款和储蓄器用e命令。

伍、自动分析:!analyze、!owner等。

陆、符号命令:.reload加载符号, .sympath设置符号路径, !sym设置符号选项。

七、进程线程:!process突显进度音信;.process展现当前经过,或用.process
/i切换当前经过;!peb展现进度环境块内容;~命令展现线程列表,用~n
s可切换当前线程,n表示线程号;.thread展现当前线程。


分析dmp文件

Windbg是调剂的利器,能够绑定进度展开调节和测试,也足以调节进度的内部存款和储蓄器印象*.dmp文件,壹般是经过崩溃后系统爆发的dmp文件,大概程序try
catch用代码生成的dmp文件。分析dmp文件,也大体上以上步骤,只可是下边是绑定文件,这些是开拓dmp文件而已。

4858.com 48

打开 dump 文件


扩展

绑定进程,调节和测试dmp文件,当然除了windbg之外,还能直接用vs编写翻译器,那是无限然而的事,只是vs编译器体积实在太大了,没有windbg小巧方便。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有