博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Windbg调试.Net应用程序
阅读量:5941 次
发布时间:2019-06-19

本文共 2648 字,大约阅读时间需要 8 分钟。

 1. 解决线上.NET应用程序的如下问题:

  • 崩溃
  • CPU高
  • 程序异常
  • 程序Hang死

2. 安装WinDbg:

3. 配置WinDbg:

运行WinDbg->菜单->File->Symbol File Path->按照下面的方法设置_NT_SYMBOL_PATH变量:

在弹出的框中输入“C:\MyCodesSymbols; SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols”(按照这样设置,WinDbg将先从本地文件夹C:\MyCodesSymbols中查找Symbol,如果找不到,则自动从MS的Symbol Server上下载Symbols)。另一种做法是从这个Symbol下载地址中,下载相应操作系统所需要的完整的Symbol安装包,并进行安装,

4. 利用WinDbg里的adplus来获取dump文件。

 Dump文件是进程的。可以把程序的执行状态通过调试器保存到dump文件中。

在WinDbg安装目录里可以找到adplus.exe,把他拖入到命令行中,然后用命令

adplus.exe -hang -pn test.exe -o c:\dumps  // 抓取当前的dump文件

adplus.exe -crash -pn test.exe -o c:\dumps  // 监听应用程序,当crash时,获取dump文件

命令-pn :应用程序名,-p:应用程序pid,-odump文件输出路径

5. 利用WinDbg加载dump文件加载调试器

运行WinDbg->菜单->File->Open Cresh dump 打开dump文件,并加载.net调试器

.loadby sos mscorwks  .Net 3.5版本及以下

.loadby sos clr  .Net 4.0

如果服务器的.Net版本与本机不匹配需要服务器版本的mscordacwks.dll文件

并设置.sympath = mscordacwks_x86_x86_2.0.50727.3607.dl

6. WinDbg的基本命令

help  sos指令帮助

!threads  显示所有线程

!dumpheap  显示托管堆的信息

!clrstack  显示调用栈

!dumpobj  显示一个对象的内容

!dumparray  显示数组

!syncblk  显示同步块

!runaway  显示线程cpu时间

!gcroot  跟踪对象内存引用

!pe  打印异常

7. WinDbg的使用

当我在Form中执行这段代码:

public Form1(){ InitializeComponent(); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); } private void UnhandledExceptionProc(object obj){ try { throw new Exception("1st chance"); } catch (Exception) { MessageBox.Show("after 1st"); } int d = 0; int n = 1 / d; }

并活动dump文件

用windbg打开dump文件后输入-pe:可以看到问题的所在。

异常如此重要,所以操作系统提供了对应的调试功能,可以使用调试器来检视异常。异常发生后,操作系统在调用用户态程序的异常处理函数前,会检查当前用户态程序是否有调试器加载。如果有,那么操作系统会首先把异常信息发送给调试器,让调试器有观察异常的第一次机会,所以也叫做first chance exception,调试器处理完毕后,操作系统才让用户态程序来处理。
如果用户态程序处理了这个异常,就没调试器什么事了。否则,程序在unhandled exception崩溃前,操作系统会给调试器第二次观察异常的机会,所以也叫做second chance exception。

《Windows用户态程序高效排错》

分析以下代码:可以看出DummyObject 会占用很多内存,甚至导致内存溢出

private void MemeryLeakProc(object obj) { while (true) { for (int i = 0; i < 100 * 1024; i++) { DummyObject o = new DummyObject(); list.Add(o); } Thread.Sleep(1000); } }

windbg命令:!dumpheap –stat 统计堆栈内存

线程Hang住的常见原因

-线程池或工作线程集中在某个耗时的工作当中,或者被其他线程锁住

核心问题,找到被hang住的线程

!threads

~*e!clrstack

!synblk

lock (syncRoot) { int tp; int io; //ThreadPool.GetMaxThreads(out tp, out io); for (int i = 0; i < 100; i++) { Thread hangThread = new Thread(HangProc); hangThread.Start(); } MessageBox.Show("Press to release lock"); }  private void HangProc(object obj)   {    lock (syncRoot) {     n = 0;    }   }

CPU高

-如果与业务量没有提升,有线程在长时间的处理

核心问题,找到占用CPU的线程

!runaway

~*e!clrstack

 

线程死锁出现的情况:

两个锁A,B,

一个线程已经拿到锁A,申请锁B,

另一个线程已经拿到锁B,申请锁A

核心问题:找到锁定的线程

!threads

!syncblk

~*e!clrstack

 

•两条指令可以解决大部分的问题
•!dumpheap –stat
•~*e!clrstack

 

 

 

 

 

 

转载于:https://www.cnblogs.com/kntao/archive/2011/12/20/2295809.html

你可能感兴趣的文章
shell-while循环
查看>>
Flink State和容错机制
查看>>
粗略的看下两款Linux下的性能分析工具
查看>>
Eclipse中使用SVN
查看>>
Play 1.x框架学习之六:未登陆拦截机制 (Not Login intercept In play framework)
查看>>
常用命令-临时记录!
查看>>
表的垂直拆分和水平拆分
查看>>
Yii CDbCriteria 常用方法
查看>>
我的友情链接
查看>>
ES学习笔记之-AvgAggregation的实现过程分析
查看>>
学习python自动化运维笔记文件比较
查看>>
PostgreSQL ODBC问题与探索SQLSpecialColumns
查看>>
Teradata join 优化
查看>>
从命令行及java程序运行MyBatis Generator 1.3.x生成MyBatis3.x代码
查看>>
sklearn API 文档 - 0.18 中文翻译
查看>>
配置404错误页
查看>>
Linux下时间戳的换算方法
查看>>
【08】Effective Java - 异常
查看>>
【01】为什么需要UML
查看>>
oracle基本实用技术
查看>>