zoukankan      html  css  js  c++  java
  • WinDbg调试C#技巧,解决CPU过高、死锁、内存爆满

    软件安装

    安装问题:执行 .loadby sos clr 命令无效

    解决办法:

    .load C:WindowsMicrosoft.NETFramework64v4.0.30319SOS.dll
    .load C:WindowsMicrosoft.NETFramework64v4.0.30319clr.dll
    .loadby sos clr

    代码调试

    查看线程

    命令: !threads 

    执行结果:

    进入线程

    命令: ~~[线程Id]s 

    执行结果:

    查看线程详情

    命令: !clrstack 

    执行结果:

    查看线程状态

    命令:  !ThreadState 线程StateId 

    执行结果:

     

    退出附加进程

    命令: qd 

    查看线程环境块(空间)

    命令:  !Teb 

    执行结果:

    查看线程堆栈

    命令:  !dumpstack 

    执行结果:

    查看局部变量

    命令:  !clrstack 

        !clrstack -l 

    执行结果:

    查看帮助

    命令:   !help 

    执行结果:

     

    查看终结器队列

    命令:  !FinalizeQueue 

    执行结果:

     

    查看线程池详情

    命令: !threadpool 

    执行结果:

     

    查看查看当前托管线程已执行时间

    命令:  !runaway 

    执行结果:

    清屏

    命令:  !cls 

    查看查看当前托管线程已执行时间

    命令:  ~*e!clrstack 

    执行结果:看所有线程的堆栈

    CPU过高的问题

    模拟CPU过高

    示例代码:

    class Program
    {
        static void Main(string[] args)
        {
            Run();
    
            Console.Read();
        }
    
        static void Run()
        {
            var task = Task.Factory.StartNew(() =>
            {
                //这是一个非常复杂的逻辑,导致死循环
                while (true)
                {
    
                }
            });
        }
    }

    生成64位Realease版本代码:

    在Bin/Realse下找到文件并运行,然后查看CPU:

    解决CUP占用过高

    创建转储文件:

    ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

    找到该转储文件:C:UsersADMINI~1AppDataLocalTempConsoleApp4.DMP

    用X64版本的WinDbg打开DMP文件:

    ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

    然后打开命令输入:

    然后输入 .loadby sos clr 与 !threads 

    现在线程少没有关系,多的话我们没有办法去判断哪个线程消耗严重,所以执行 !runaway 查看当前托管线程已执行时间

    切换到指定线程 ~~[4f78]s ,执行  !clrstack  查看当前线程的调用堆栈

    从调用堆栈上来看,当前线程 在 Program+c.b__1_0() 方法之后23行就没有调用堆栈了,说明方法在这个地方停滞不前了。

    最后反编译源码到指定的方法中去查看

    方法二:

    通过 !dumpdomain 拿到程序地址

    然后反编译成dll输出文件 !savemodule 00007ff7e4f94120 c:21.dll (文件夹必须存在)

    然后找到该dll进行反编译

    死锁问题

    模拟死锁

    实例代码:

    class Program
    {
        static void Main(string[] args)
        {
            new Program().Run();
    
            Console.Read();
        }
    
        void Run()
        {
            lock (this)
            {
                var task = Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("-------start-------");
                    Thread.Sleep(1000);
    
                    Run2();
                    Console.WriteLine("---------end--------");
                });
    
                task.Wait();
            }
        }
    
        void Run2()
        {
            lock (this)
            {
                Console.WriteLine("------我是Run2------");
            }
        }
    }

    执行结果:

    解决死锁

    然后用WinDbg附加到进程,执行 .loadby sos clr 与 !threads 查看当前的托管线程

    然后执行 ~*e!clrstack 查看所有线程的堆栈

    可以看出主线程在等待

    执行 !syncblk 查看当前哪个线程持有锁,可以看出主线程持有锁

    可以看得出“主线程”持有当前的同步锁

    内存爆满

    模拟内存爆满

    实例代码:

    class Program
    {
        static StringBuilder sb = new StringBuilder();
        static void Main(string[] args)
        {
            for (int i = 0; i < 10000000; i++)
            {
                sb.Append("hello world");
            }
    
            Console.WriteLine("执行完毕");
            Console.Read();
        }
    }

    解决内存爆满

    然后用WinDbg附加到进程,执行  .loadby sos clr 与  !threads ,然后执行  !dumpheap -stat 查看clr的托管堆中的各个类型的占用情况

    然后看到了有13768个char[]数组

    然后执行 !DumpHeap /d -mt 00007ff841318610    //查看当前的方法表

    然后执行 !DumpObj /d 0000022baed1dec8 //查看当前char[]的内容

    然后执行 !gcroot 00000135a60f4940 查看当前地址的Root。。。

     

    所以结合“StringBuilder”,结合 ”hello world“ 我们就找出了问题。。。

  • 相关阅读:
    1104 Sum of Number Segments (20 分)(数学问题)
    1092 To Buy or Not to Buy (20 分)(hash散列)
    1082 Read Number in Chinese (25 分)(字符串处理)【背】
    1105 Spiral Matrix (25 分)(模拟)
    初识网络安全及搭建网站(内网)
    HTML5开发者需要了解的技巧和工具汇总(转)
    native+web开发模式之web前端经验分享
    移动平台3G手机网站前端开发布局技巧汇总(转)
    Asp.net 中图片存储数据库以及页面读取显示通用方法详解附源码下载
    使用H3Viewer来查看VS2010的帮助文档
  • 原文地址:https://www.cnblogs.com/wyt007/p/10014481.html
Copyright © 2011-2022 走看看