debugging_debugging with gdb - CSDN
精华内容
参与话题
  • 查找和改正错误的过程称为调试(debugging)。调试的一般途径是采用各种方法逐步缩小程序中bug所在的范围。

    对于代码调试(debugging)的释义以及进行调试的基本方法小结

    概述:查找和改正错误的过程称为调试(debugging)。调试的一般途径是采用各种方法逐步缩小程序中bug所在的范围。

    在这里插入图片描述

    1、手工跟踪(hand trace)

    手工跟踪(hand trace)程序(即通过读程序找错误),也可以插入打印语句,显示变量的值或程序的执行流程。这种方法适用于短小、简单的程序。

    2、使用调试工具

    对于庞大、复杂的程序,最有效的调试方法还是使用调试工具。

    JDK包含了一个命令行调试器 Jdb,结合一个类名来调用该命令。Jdb 本身也是一个 Java 程序,运行本身的一个 Java 解释器的拷贝。所有的 Java IDE 工具,比如 Eclipse 和 NetBeans 包含集成的调试器。调试器应用让你可以跟踪一个程序的执行。他们因程序的不同,但是大都支持以下特征中的多数:

    • 一次执行一条语句:调试器允许你一次执行一条语句,从而可以看到每条语句的效果。
    • 跟踪进入或者一步运行过一个方法:如果一个方法正在被执行,你可以让调试器跟踪进入方法内部,并且一次执行方法里面的一条语句,或者你可以让调试器一步运行过整个方法。如果你知道方法是可行的,你应该一次运行过整个的方法。比如,通常都会一步运行过系统提供的方法,比如,System.out.println
    • 设置断点:你可以在一条特定的语句上面设置断点。当遇到一个断点时,你的程序将暂停。你可以设置任意多的断点。当你知道程序错误从什么地方可能开始的时候,断点特别有用。你可以将断点设置在那条语句上,让程序先执行到断点处。
      关于使用Eclipse进行断点调试的方法请移步这里——如何使用 Eclipse 进行断点调试?
    • 显示变量:调试器让你选择多个变量并且显示他们的值。当你跟踪一个程序的时候,变量的内容持续更新。
    • 显示调用堆栈:调试器让你跟踪所有的方法调用。当你需要看到程序执行的流程的宏观图景的时候,这个特征非常有用。
    • 修改变量:一些调试器允许你在调试的过程中修改变量的值。当你希望用不同的示例来测试程序,而又不希望离开调试器的时候,这是非常方便的。

    感谢大家的支持,我是白鹿,一个不懈奋斗的程序猿。希望本贴能帮助到大家,大家如果还有什么问题、建议或者补充可以留言在帖子下方,给予更多人帮助,同时我看到了也会及时回复,让我们一起努力!更多一手资讯请大家关注本人微信公众号:WDeerCode代码圈!
    在这里插入图片描述

    展开全文
  • 【知识笔记】Debugging

    2019-06-25 18:00:43
    一、启动调试出现 无法启动程序 当前状态中是非法 VS工具--选项--调试--常规--启用asp.net的JavaScript调试(chrome和ie)去掉勾选 二、web.config中<customErrors>报错 ...节点用于定义一些自定义错误信息...

    一、启动调试出现 无法启动程序 当前状态中是非法

    VS工具--选项--调试--常规--启用asp.net的JavaScript调试(chrome和ie)去掉勾选

    二、web.config中<customErrors>报错

    <customErrors>节点用于定义一些自定义错误信息的信息。

    此节点有Mode和defaultRedirect两个属性,其中

    defaultRedirect属性是一个可选属性,表示应用程序发生错误时重定向到的默认URL,如果没有指定该属性则显示一般性错误;

    Mode属性是一个必选属性,它有三个可能值,它们所代表的意义分别如下:
    Mode 说明
    On 表示在本地和远程用户都会看到自定义错误信息。
    Off 禁用自定义错误信息,本地和远程用户都会看到详细的错误信息
    RemoteOnly 表示本地用户将看到详细错误信息,而远程用户将会看到自定义错误信息。
    这里有必要说明一下本地用户和远程用户的概念。当我们访问asp.net应用程时所使用的机器和发布asp.net应用程序所使用的机器为同一台机器时成为本地用户,反之则称之为远程用户。

    开发调试阶段为了便于查找错误Mode属性建议设置为Off,而在部署阶段应将Mode属性设置为On或者RemoteOnly,以避免这些详细的错误信息暴露了程序代码细节从而引来黑客的入侵。

    所以想看具体的错误,有两种方式:将mode设置为Off,或者直接在服务器上复现刚才发生错误的操作,看详细的错误信息。

    参考:关于web.config中<customErrors>节点说明

     

    三、WCF报错

    1、WCF运行不起来

    System.ServiceModel.EndpointNotFoundException:“没有终结点在侦听可以接受消息的

     "ExceptionMessage": "没有终结点在侦听可以接受消息的 http://localhost.dev.xxx.com/Services/yyyService.svc。这通常是由于不正确的地址或者 SOAP 操作导致的。如果存在此情况,请参见 InnerException 以了解详细信息。","ExceptionType": "System.ServiceModel.EndpointNotFoundException",

    可能是 wcf服务没启动?

    从IIS_Express中打开wcf站点,看是否有报错,

    可能错误:未能加载配置文件;web.Config中wcf路径配置有误

    路径错误,看是否需要修改.vs\config\applicationhost.config 中的虚拟路径  <virtualDirectory path="/Service" physicalPath="D:\sources.git\xxx\yyy" />

    配置文件拷贝后,WCF运行起来。

    2、调试不进断点

     调试选项里面的 “仅我的代码”,取消选中

     

     

    3、无法自动进入并单步执行服务器。调试器未能在服务器进程中停止

     

    以上设置都配置好后,清理解决方案,重新生成。

     4、域名绑定问题

     

    可以看到,restapi请求WCF时 没有成功。

    在本地看到wcf是ok的。但是在restapi所在的服务器上请求wcf是不行的。于是看服务器上的host,发现没有绑定 wcf域名对应的ip。

    四、DBContext报类型初始值设定项引发异常

    查看配置文件,configSource节点

    <appSettings configSource="VConfigs\Dev\appSettings.config">

        <add key="ClientSettingsProvider.ServiceUri" value=""/>

      </appSettings>

    手动改为

    <appSettings configSource="VConfigs\Dev\appSettings.config"/>

    参考:http://www.it1352.com/21840.html

    五、  Missing type map configuration or unsupported mapping

    Missing type map configuration or unsupported mapping. Mapping types: Discount -> DiscountEntity Ferry.Data.Models.Discount ->Entity.DiscountEntity Destination path: List`1[0] Source value: Data.Models.Discount,錯誤源:

    参考:http://www.cnblogs.com/dudu/p/5875579.html

    从 GitHub 上签出 AutoMapper 的源代码一看 Mapper.Initialize() 的实现,恍然大悟。

    public static void Initialize(Action<IMapperConfigurationExpression> config)

    {

        Configuration = new MapperConfiguration(config);

        Instance = new Mapper(Configuration);

    }

    原来每次调用 Mapper.Initialize() 都会创建新的 Mapper 实例,也就是多次调用 Mapper.Initialize() 只有最后一次生效。

    更多参考:【.NET】AutoMapper学习记录

     

    六、the current .NET SDK does not support targeting .NET Standard 2.0. Either target .NET Standard 1.6 or lower, or use a version of the .NET SDK that supports .NET Standard 2.0

    通过这句英文一直以为是 .net framework 2.0未安装。

    安装以后引用不报错(没有黄色感叹号),编译的时候却还是报错。

     找到原因,原文地址

    https://stackoverflow.com/questions/45732236/the-current-net-sdk-does-not-support-targeting-net-standard-2-0-error-in-visua

     安装 .net core 2.0可以解决。

    vs重启后,出错的项目 属性。重新选择目标平台。

     

    七、未能找到文件

    “D:\sources.git\wingontravel_SZ\Ferry\DEV\Ferry\Ferry.Offline\App_Data\XmlDocument.xml”

    重新编译offline项目,并且index.html为启动页面。。

    让D:\sources.git\wingontravel_SZ\Ferry\DEV\Ferry\Ferry.Offline\App_Data 目录下生成这个xml文件,或者拷贝过来。

     

    八、初始化异常或内存不足

    System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.

    日志记录的详细信息:

    System.TypeInitializationException: The type initializer for 'Ferry.Data.Models.FerryDBContext' threw an exception.

    ---> System.TypeInitializationException: The type initializer for 'System.Data.Entity.Utilities.TypeExtensions' threw an exception.

    ---> System.TypeInitializationException: The type initializer for 'System.Data.Entity.Core.Metadata.Edm.MetadataItem' threw an exception.

    ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.

    咋一看是数据库(或者EF连接)初始化的问题。

    若期间没有动过服务器或者DB,,则大致可以认为是服务器问题,可以重启服务,只重启出问题的应用程序池

     

    九、https网站中样式资源没起作用

    F12 看到js报错:Mixed Content: The page at 'https://xxx.com//app/#booking/search'

    was loaded over HTTPS, but requested an insecure stylesheet 'http://xxx.com/Site/Styles/offline/main.css'.

    This request has been blocked; the content must be served over HTTPS.

     

    http://xxx.com/Site/Styles/offline/main.css这个资源(位于index.html中的<head>标签中)被阻塞了,

    原因:在https网站中,载入http网站的资源(网页、图片等),会被浏览器阻拦。HTTPS 是 HTTP over Secure Socket Layer,以安全为目标的 HTTP 通道,在 HTTPS 承载的页面上不允许出现 http 请求

    正确应该是https://xxxx.com/Site/Styles/offline/main.css

     

    十、未能加载文件或程序集

    打开WCF时:未能加载文件或程序集“MongoDB.Bson, Version=2.2.3.3, Culture=neutral, PublicKeyToken=null”或它的某一个依赖项。系统找不到指定的文件。

    找到相应的目录:D:\sources.git\xxx\DEV\yyy.Offline.Service.Site\bin

    看它里面是否有MongoDB.Bson程序集,没有的话copy一份进去。

    十一、分析器错误信息: 未能加载类型“xxxx.Global”

    解决方法: 删除此项目下bin里面的所有dll,清理 重新生成。

    十二、VS中修改代码,再断点调试,发现命中的还是修改前的代码

    解决方法: 清理解决方案,再重新生成。

    十三、LINQ to Entities 不识别方法“System.DateTime ToDateTime(System.String)”,因此该方法无法转换为存储表达式

     

    因为LINQ语句最后都是要转为sql语句来执行的,当它转换后,发现sql语句中要执行的方法“XX”,并不是一个在数据库中的存储过程函数,也无法进行转换为存储表达式。

    即EF不支持复杂类型(如实体)的直接检索,只能用简单类型(string、int、guid等)

    类似异常:LINQ to Entity 不识别方法“System.String ToString()”,因此该方法无法转换为存储表达式

    最近在项目中遇到需求说,要模糊查询。于是有 

    var query = store.Repository.Set<EFHotelOrder>().Where(p => p.OrderType == (byte)OrderType.Expert);
    if (request != null)
    {
    if (request.OrderID != null)
    {
    query = query.Where(i => i.OrderID.ToString().Contains(request.OrderID.ToString()));
    }
    if (request.CityName != null)
    {
    query = query.Where(i => i.CityName.Contains(request.CityName));
    }
    View Code

    由于orderId被设计为了int型,故用了toString()。所以报了上面的错误。

    参考:LINQ to Entities 不识别方法“System.String ToXX()”,因此该方法无法转换为存储表达式

    LINQ to Entity 不识别方法“System.String ToString()”,因此该方法无法转换为存储表达式

    而此处遇到的是int型的模糊匹配问题,不适用,后来在网上发现:EF中 int没有模糊查询的概念;一般模糊查询都是针对字符串

     

    十四、你的xxx.mdf 的版本为 782,无法打开,此服务器支持 655 版及更低版本,不支持降级路径

      现象:在vs2015中直接添加数据库和表,

      查找资料:782是sql server 2014的内部版本号(是vs2015自带的)、655是sql server2008(本机安装的数据库版本)

      原因:你的mdf数据库文件是12.00.2000版本,而你的SQLEXPRESS却是2008

    (SQL Server Express 是由Microsoft所开发的SQL Server的其中一个版本,SQL Server Express 有 2005 、 2008 与 2008 R2 、2012 R0和最新的 2014五个版本)

          

    查看数据库的版本,SSMS版本

     你调用的数据库文件版本太高,当前的数据库不支持,你只能将调用的数据库版本降低

    解决:在本机只安装了sql server2008的情况下,数据库也要用管理工具创建的数据库,不能用vs2015上直接创建的

    十五、基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系

      当我们有时用代码编写post/Get请求url远程地址会报“基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。 ---> System.Security.Authentication.AuthenticationException: 根据验证过程,远程证书无效

    ”这个异常,是因为远程url使用的域名 没有购买证书,所以用以下方式来解决:

    在create url之前 设定“获取或设置用于验证服务器证书的回调”永远为true 即可,具体如下

    请求一定需要:

    ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidate;
    System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
    
    private static bool RemoteCertificateValidate(object sender, X509Certificate cert,X509Chain chain, SslPolicyErrors error)
            {
                //为了通过证书验证,总是返回true
                return true;
            }

    或者

     ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Ssl3;
     ServicePointManager.ServerCertificateValidationCallback += (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) => true;


    十六、Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type 'System.Collections.Generic.List

      无法将Newtonsoft.Json.Linq.JArray隐式转换为List<T> 

    现在webapi一般使用json,

    eg: data (Array[CollectionListItemExtend], optional):  返回data。。类型为JArry,那直接用List<>去接收,就会报上面的错误。

     在后台接口获取参数时,我们可以使用dynamic,如:

    dynamic jArray = HttpHelper<string, RestAPIGetAccount<object>>.GetDataBy=API(url).Result;
                //JArray jArray = new JArray();
                //jArray.ToObject()
                if (jArray != null && jArray.head != null && jArray.head.code == 0)
                {
                    List<AccAPI.CollectionListItemExtend> temp = jArray.data.ToObject(typeof(List<AccAPI.CollectionListItem>));
                    if (temp != null && temp.Count > 0)
                    {
                        string str = temp.ToJSON();
                        System.Console.ReadLine();
                    }
                }
    
     public static async Task<RestAPIGetAccount<object>> GetDataBy(string url)
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Ssl3;
                ServicePointManager.ServerCertificateValidationCallback += (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) => true;
    
                var rs = new RestAPIGetAccount<object>() { head = new Entity.API.OfflineResponseHeader() };
                using (HttpClient client = GetHttpClient(url, 100))
                {
                    try
                    {
                        var httpResponseMessage = client.GetAsync(url).Result;
                        if (!httpResponseMessage.IsSuccessStatusCode)
                        {
                            var xmlResult = httpResponseMessage.Content.ReadAsStringAsync().Result;
                            rs.head.code = 500;
                            rs.head.message = "http请求失败";
                        }
                        else
                        {
                            var result = httpResponseMessage.Content.ReadAsStringAsync().Result;
                            if (!string.IsNullOrWhiteSpace(result))
                            {
                                rs = result.FromJSON<RestAPIGetAccount<object>>();
                            }
                        }
                    }
                    catch (AggregateException ae)
                    {
                        var exceptions = ae.InnerExceptions.ToList();
                        rs.head.message = string.Join(",", exceptions.Select(p => p.ToString()).ToArray());
                        rs.head.code = 500;
                        HotelHelper.WriteErrorLog(LogSourceType.Common, $"Get数据", $"url:{url}{Environment.NewLine}rs:{rs.ToJSON()}{Environment.NewLine}message:{ae.ToString()}");
                    }
                    catch (Exception ex)
                    {
                        rs.head.message = ex.ToString();
                        rs.head.code = 500;
                        HotelHelper.WriteErrorLog(LogSourceType.Common, $"Get数据", $"url:{url}{Environment.NewLine}rs:{rs.ToJSON()}{Environment.NewLine}message:{ex.ToString()}");
                    }
                }
                return rs;
            }
    
    
    
    public class RestAPIGetAccount<T>
        {
            /// <summary>
            /// 返回data
            /// </summary>
            public T data { get; set; }
    
            /// <summary>
            /// 
            /// </summary>
            public OfflineResponseHeader head { get; set; }
        }
        public class OfflineResponseHeader
        {
            /// <summary>
            ///   0-success, (客户端错误400-499) 401未登录, 403没访问权限, (异常500-599) 500-error, 
            /// </summary>
            public int code { get; set; }
            /// <summary>
            /// 錯誤信息
            /// </summary>
            public string message { get; set; }
        }
    View Code

    其实是 Newtonsoft.Json.Linq.JArry.ToObject()

     更多参考:Newtonsoft.Json.Linq.JArray转换为List    Convert JSON to a Type

     

    十七、CS0656 C# 缺少编译器要求的成员“Microsoft.CSharp.RuntimeBinder.Binder.Convert”

      在使用 dynamic 时生成失败,遇到这样一个错。

    解决方法:在项目中添加对 "Micorsoft.CSharp.dll" 的引用

    十八、 SqlDateTime 溢出,必须介于 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM之间

      原因:.NET中  DateTime最小值为: 0001-1-1 0:00:00

            数据库中DateTime最小值为: 1753-1-1 0:00:00,

    很明显:.NET中的最小值超出了数据库时间类型的最小值,导致数据溢出的错误。(两者的最大值都是一样滴)

    出现这种问题多半是因为插入或者更新数据库时,datetime字段值为空默认插入0001年01月01日造成datetime类型溢出

     传给数据库表的时间类型值是null值。这里的null指的是程序代码中的null,多数出现这种情况的场景是:在程序里面定义了一个时间类型的变量,没有给赋值,就传给数据库,这时这个变量的值默认是赋成了01年01月01日;由于数据库中DateTime类型字段,最小值是1/1/1753 12:00:00,而.NET Framework中,DateTime类型,最小值是1/1/0001 0:00:00,显然,超出了sql的值的最小值范围,导致数据溢出错误。

      解决方法: 

    方法1、使用System.Data.SqlTypes.SqlDateTime.MinValue替代System.DateTime类型,这样SqlDateTime的MinValue和Sql中DateTime的范围吻合,就不会再出现以上的错误了。

    方法2、DateTime为空或最小时,给其赋一个SqlDateTime最小值或者特定值

    if (modelberthStatus.TIMEIN == null || modelberthStatus.TIMEIN == DateTime.MinValue)
           {
            modelberthStatus.TIMEIN = SqlDateTime.MinValue.Value;
            }
    //或者:  modelberthStatus.TIMEIN = new DateTime(1900,1,1);

     

    转载于:https://www.cnblogs.com/peterYong/p/10647999.html

    展开全文
  • 软件构造 6-4 Debugging

    2020-06-19 22:49:38
    6.4 代码调试 一. Bug 与 Debug   DeBug 的方法(优先选上面一种方法):   Debug 是保证程序质量(之前是防御式编程、测试,并且其与前两者均不是最影响程序质量的核心手段)或修复程序错误的最后一个手段。...

    6.4 代码调试

    一. BugDebug

      DeBug 的方法(优先选上面一种方法):
    在这里插入图片描述
      Debug保证程序质量(之前是防御式编程、测试,并且其与前两者均不是最影响程序质量核心手段)或修复程序错误最后一个手段。
      Debug 的目的是寻求错误的根源并消除它。但 debug 会占用大量的时间。


      Debug 是测试的后续步骤:测试发现问题, debug 消除问题。
      Debug困难的:

    • “症状”和“原因”可能相隔很远,高耦合导致的结果
    • 当其他 bug 被修复后,该 bug 消失了
    • 例如四舍五入造成的不准确
    • 因为人工错误导致 bug 的症状难以有效追踪
    • 有些症状是由计时 定时等时间原因导致的
    • 难以重现出错时的输入数据
    • 由于外部软硬件环境变化,导致间歇性的症状
    • 分布式导致的问题

    二. Debug 的过程

      Debug 的过程:

    • 重现 bug
    • 诊断 bug
    • 修复 bug
    • 反思
      在这里插入图片描述

      错误定位占据了绝大部分的调试时间。
      针对这种问题,研究者研究问题:自动化错误定位。但普通人常用的方法为:假设-检验(即通常的暴力搜索)。

    1. 复现 bug

      从最小测试用例集开始复现错误。

    • 确定有哪些因素跟 bug 相关,将这些因素找出来并变化它们的值。
    • 确保你的 bug 复现环境软件版本软件的运行环境输入数据)跟用户发现 bug 的环境尽可能保持一致。

    2. 诊断 bug

      定位 bug 的手段有:

    • 测量,如 logging
    • 分治,或称 Wolf fence algorithm(防狼围栏算法)

    在这里插入图片描述

    • 切片,特征值 x 出错了,找出程序中有助于计算特定值 x 的部分。如:
      在这里插入图片描述
      或如下程序中 tax 出错了,查看标红片段:
      在这里插入图片描述
    • 寻找差异
      (1). Leveraging VCS 充分利用版本控制系统,找出在哪个 commit 之后出现了 bug 症状。例如版本控制工具 git 使用类似分治方法探索不同的 commit ,但指定具体的一部分 commit 出错需要用户来指定。
      (2). 基于差异的调试:两个测试用例,分别通过/未通过。通过查找二者所覆盖的代码之间的差异,快速定位出可能造成 bug 的代码行。如下图,通常执行最少的语句(6、7行)可能出现错误。
      在这里插入图片描述
      (3). 查找其他方面的差异:软硬件环境、 JVM 参数配置、输入文件、……
    • 符号化 debug:符号化执行,即不需输入特定的值,使用“符号值”(而实际值”)作为输入解释器模拟程序执行,获得每个变量的“符号化表达式”,从而可判断是否执行正确。
      符号化执行程序的三个状态
      各变量的符号化取值
      路径条件 PC
      计数器
      符号化执行树在这里插入图片描述
    • 调试器
    • 其他方法

    三. Debugging 工具

    0. 暴力方式

      假设-验证:假设原因,验证原因。可以通过技巧:

    • 看内存导出文件
    • 到处 println()
    • 自动化调试工具

    1.1 Memory dump

      不同版本 Java 内存管理方式可能不同,如 Java 8Java 10 的内存管理方式不同;不同语言的内存管理方式可能不同。

    1.2 Stack trace

      根据信息知道

    • 实际抛出异常的位置。(信息第一行)
    • 在您自己的代码中执行的最后一行。(信息中出现自己程序的第一行)
    • 你的代码的入口点,也就是你的代码的方法在堆栈跟踪中首先被调用?(信息中心出现自己程序的最后一行)
    • 此执行的入口,Junit测试。(信息最后一行)
      在这里插入图片描述
        具体获取栈内容(7.2节):
    Throwable t = new Throwable();
    StringWriter out = new StringWriter();
    t.printStackTrace(new PrintWriter(out));
    String description = out.toString();
    //or
    public class WhoCalled {
    	static void f() {
    		// Generate an exception to fill in the stack trace
    		try {
    			throw new Exception();
    		} catch (Exception e) {
    			for(StackTraceElement ste : e.getStackTrace())
    				System.out.println(ste.getMethodName());
    		}
    	}
    	static void g() { f(); }
    	static void h() { g();}
    	public static void main(String[] args) {
    		f();
    		System.out.println("--------------------------");
    		g();
    		System.out.println("--------------------------");
    		h();
    	}
    }
    //or
    Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
    for(Thread t : map.keySet()){
    	StackTraceElement[] frames = map.get(t);
    	//... analyze frames
    }
    

      上面的第二种方法输出

    f
    main
    --------------------------
    f
    g
    main
    --------------------------
    f
    g
    h
    main
    

    1.3 Printf debugging

      在程序内部各部分展示程序执行时的动态信息,比使用静态dump 分析更有效。
      来源于 C 语言。一旦软件对外发布****,所有用于 debugprint 语句都要去除或禁用

    • 可以选择注释,但速度慢效率低
    • 委托
    //Coding & debugging
    public static void MyPrint(String in) {
    	System.out.println(in);
    }
    MyPrint("Entering callMethod ");
    result = callMethod();
    MyPrint("The result is " + result);
    //Released
    public static void MyPrint(String in) {
    	//System.out.println(in);
    }
    MyPrint("Entering callMethod ");
    result = callMethod();
    MyPrint("The result is " + result);
    

    1.4 Logging

      通过设定日志级别来确定要 log 哪些信息;log 结果可被多种渠道加以处理,可通过设定条件进行过滤,并输出为多种格式;可使用层次化的多个日志记录器。结构如下:
    在这里插入图片描述
      针对一个应用,为其设定全局的 logger:

    import java.util.logging.*;
    Logger.getGlobal().info("File -->Open menu item selected");
    /*
    Results:
    May 10, 2018 10:12:15 PM LoggingImageViewer main
    INFO: File -->Open menu item selected
    */
    

      关闭日志命令:

    Logger.getGlobal().setLevel(Level.OFF);
    

      使用全局 logger 导致信息混乱,可以定义自己的 logger

    import java.util.logging .*;
    private static final Logger myLogger = 
    				Logger.getLogger("com.mycompany.myapp");
    //often using class name as logger name
    
    //Or
    
    public class LogTest {
    	static String strClassName = LogTest.class.getName(); //get class name
    	static Logger myLogger = Logger.getLogger(strClassName);
    	// using class name as logger name
    	……
    	myLogger.info("XXXX");
    }
    

      对于日志的输出,可以输出到控制台(缺省)。对于日志的处理,日志处理器也需要设定日志级别。

    public class LevelTest {
    	private static String name = test.class.getName();
    	private static Logger log = Logger.getLogger(name)
    	public void sub() {
    		log.setLevel(Level.FINEST);
    		log.setUseParentHandlers(false);
    		Handler handler = new ConsoleHandler();
    		handler.setLevel(Level.FINEST);
    		log.addHandler(handler); //将 logger 和相应的 handler 捆绑在一起, delegation
    		
    		log.severe("severe level");
    		log.warning("warning level");
    		log.info("info level");
    		log.config("config level");
    		log.fine("fine level");
    		log.finer("finer level");
    		log.finest("finest level");
    	}
    }
    

      除了控制台处理器 ConsoleHandler ,还可以设定其他的 handlers

    • SocketHandler 网络
    • FileHandler 文件
    • StreamHandler
    • ConsoleHandler
    • MemoryHandler

      可以选用不同的格式:

    • SimpleFormatter 人类可读格式
    • XMLFormatter

    1.5 编译器警告信息

      为了正确性,我们可以把编译器的 warning level 调到最高级别,消除所有 warning;精益求精,把 warningerror 看待;学着把编译器当作自己的老师,搞清楚每一个 warning ,并在后续代码中避免。

    1.6 Debugger

    • Breakpoints 设置断点
      执行方式有
      Step Over
      Step Into
      Step Return
    • Single-stepping 单步执行
    • Resume operation 恢复运行
    • Temporary breakpoints 临时断点
    展开全文
  • 6-4 debugging

    2020-06-08 12:25:10
    1 什么是bug?什么是debug? bug:–程序中的一种错误,它导致程序以非预期或非预期的方式执行。 –包含大量错误和/或严重干扰其功能的错误的程序称为错误。 –详细说明程序中错误的报告通常称为错误报告、故障报告...

    1 什么是bug?什么是debug?
    bug:–程序中的一种错误,它导致程序以非预期或非预期的方式执行。
    –包含大量错误和/或严重干扰其功能的错误的程序称为错误。
    –详细说明程序中错误的报告通常称为错误报告、故障报告、问题报告、故障报告、缺陷报告等。

    为什么会出现bug?
    –代码错误
    –未完成的需求或不够详细
    –对用户需求的误解
    –设计文档中的逻辑错误
    –缺少文档
    –没有足够的测试

    当防御式编程和测试都没能抵挡bug时,你就不得不进行调试了

    什么是debug?
    ▪ 调试是识别错误的根本原因并加以纠正的过程。
    –与测试(最初是检测错误的过程)相反,调试是测试成功的结果。
    –在一些项目中,调试占据了整个开发时间的50%。
    –对于许多程序员来说,调试是编程中最困难的部分。
    ▪ 与测试一样,调试并不是提高软件质量的方法,而是诊断缺陷的方法。
    –软件质量必须从一开始就内置。构建高质量产品的最佳方法是仔细开发需求,设计良好,并使用高质量的编码实践。
    –调试是最后的手段。
    在这里插入图片描述
    可以看出写程序慢的程序员花了大量的时间在debug上

    ▪ 调试不是测试,而是测试的结果。
    –调试过程从执行测试用例开始。
    –评估结果,发现预期结果与实际结果之间缺乏对应性。
    –调试过程试图将症状与原因相匹配,从而改正错误。

    有时候bug的原因和bug发生的地方可能相隔很远,高耦合加剧了这种情况。有时候bug不是由于错误引起的,而是由于系统,例如舍入误差。

    错误可能是由于时间问题造成,可能很难复现,可能是间歇性的,可能是由于分布在不同的处理器造成的…

    2 调试过程
    包括四步:
    ▪ 再现:找到一种方法来可靠和方便地按需再现问题。
    ▪ 诊断/定位:构建假设,并通过执行实验对其进行测试,直到已经确定了错误的根本原因。
    ▪ 修正:设计并实现修正问题、避免引入回归、维护或提高软件整体质量的变更。
    ▪ 反思:吸取错误的教训。哪里出了问题?有没有其他同样的问题也需要解决的例子?你能做些什么来确保同样的问题不再发生?
    在这里插入图片描述
    调试中的查找错误占据了debug的绝大多数时间。

    (1) 复现错误
    首先找到一个产生失败的小的可重复测试用例:可以从测试用例中寻找;如果该错误是用户报告的,则复现较难;如果错误是线程中出现的,则重现较难。

    错误发生时源代码的差异会导致你难以复现bug,我们需要确定哪些因素和bug相关,尽量确保环境和变量一致。包括软件版本,软件运行环境,bug发生时输入的数据等。
    (2) 诊断错误
    1.插桩:我们可以使用插桩代码,比如日志logging来对代码的行为进行记录和了解。
    2.分治:通过排除错误模块来定位bug发生的地方
    eg:防狼围栏算法
    在这里插入图片描述
    3.切片
    ▪ 切片意味着找到程序中有助于计算特定值的部分。
    –当出现故障时(程序中某个特定点的错误值),该值的切片由帮助计算错误值的程序行组成。
    –导致错误值的bug位于该片段的某个位置
    在这里插入图片描述
    4.集中注意力在差异上
    可以利用版本控制系统,查找在哪次推送后发生了bug
    可以使用git-biset命令来查找bug
    在这里插入图片描述
    (2) 增量调试将错误的原因定义为成功执行与失败执行之间的差异,然后搜索最小原因以查找问题。

    还有其他方面的差异:查找其他方面的差异:软硬件环境、JVM参数配置、输入文件、…

    *符号化执行:一种分析程序的方法,以确定哪些输入导致程序的每个部分执行。–解释器跟随程序,假设输入值是符号值,而不是像程序的正常执行那样获取实际输入,这是一种抽象解释。–这样,它就得到了程序中表达式和变量的符号表达式,以及每个条件分支的可能结果的符号约束。
    符号执行树–符号执行树中的每个节点提供完整状态和相关信息,如符号调用堆栈或到达节点的路径条件。
    在这里插入图片描述
    6 调试器Debugger
    ▪ 调试器——调试器在复杂度和功能上都有很大的不同,从简单的面向命令行的示例到完全集成到图形化IDE中的示例。
    –它们允许我们在执行时检查代码、设置断点、单步执行和检查程序状态。
    ▪ 它在开发生命周期的三个不同点上特别有用:在最初的开发过程中,单步执行代码有助于说服我们,它真正做的事情与我们认为我们正在实现的东西是一致的。
    –如果我们有一个关于代码为什么以特定方式运行的理论,我们可以使用调试器来确认或反驳这个理论。
    –最后,调试器可以帮助我们探索行为方式根本无法理解的代码。

    7: 向他人学习
    ▪ 有时,这个bug会涉及到一种广泛使用的技术(例如,编译器,正在使用的库或框架),在这种情况下,可能会有其他人在您面前遇到同样的问题。
    ▪ 在这种情况下,对网络的一点研究可以带来好处。也许有人在论坛上问了一个关于同一类故障模块的问题,或者写了一篇博客文章描述了他们陷入的陷阱,结果发现正是你发现自己陷入的陷阱。

    3 调试工具

    暴力调试:最常见,受欢迎
    优点:不需要太多思考
    缺点:效率低下,成功率低
    分类::使用内存转储进行调试;
    根据“在程序中分散打印语句”的常见建议进行调试,使用println打印
    使用自动调试工具进行调试。

    (1) 事后调试:内存转储
    ▪ 内存转储:硬盘上的一种文件,包含某一特定时间进程内存内容的副本,当进程因某种内部错误或信号而中止时产生。
    ▪ 当程序中止时,可以进行内存转储,以便在崩溃时检查程序的状态。
    (2) 事后调试:堆栈跟踪
    通过调用可抛出类的printStackTrace方法,可以访问堆栈跟踪的文本描述。
    一种更灵活的方法是getStackTrace方法,它生成一个StackTraceElement对象数组,您可以在程序中对其进行分析。
    StackTraceElement类有方法来获取执行代码行的文件名和行号以及类和方法名。toString方法生成一个包含所有这些信息的格式化字符串
    (3) Printf调试
    在失败的程序中分散语句以显示变量值比转储好,因为它不是静态的,并且显示程序的动态性。
    ▪ 打印调试(或跟踪)是监视(实时或记录的)跟踪语句或打印语句的行为,这些语句指示进程的执行流。
    ▪ 由于在C中使用printf函数,这有时称为printf调试。
    ▪ 它是使用printf()或系统输出打印(例如,)语句。
    ▪ 很简单但很有效。
    一旦软件对外发布,所有用于debug的print语 句都要去除或禁用。

    (4) Logging日志
    日志可以定向到不同的处理程序,可以控制台输出或者写入文件
    默认情况下日志记录由配置文件控制
    在这里插入图片描述
    ▪ 对于简单的日志记录,使用全局记录器并调用其info方法
    如果不想使用全局的logger,可以创建自己的logger
    设置日志级别:高于某级别的才会被记录在这里插入图片描述
    默认情况下日志会输出到控制台
    使用FileHandler将日志记录到文件中
    SockerHandler将日志发送到指定主机和端口
    StreamHandler:将格式化记录写入OutputStream的简单处理程序。
    ConsoleHandler:一个简单的处理程序,用于将格式化记录写入系统错误
    FileHandler:处理程序将格式化的日志记录写入单个文件或一组日志文件。
    SocketHandler:将格式化日志记录写入远程TCP端口。
    ▪ MemoryHandler:处理程序缓冲内存中的日志记录。
    SimpleFormatter:编写简短的“可读”日志记录摘要。▪ XMLFormatter:写入详细的XML结构化信息。

    外部日志记录
    ▪ 通过拦截软件与其他地方之间的通信量,可以从软件外部获取有用信息(外部日志记录)。
    ▪ 可以在客户端和服务器之间插入代理。如果您正在使用的协议不存在代理,或者您找不到配置代理以拦截流量的方法,则可以考虑使用网络分析器来捕获所有网络流量

    (5) 编译器警告消息
    ▪ 最简单和最有效的调试工具之一是您自己的编译器。
    ▪ 将编译器的警告级别设置为可能的最高、最挑剔的级别,并修复代码,使其不会产生任何编译器警告。
    ▪ 假设编写编译器的人比你更了解你的语言。–如果他们警告你一些事情,通常意味着你有机会学习新的语言。–努力理解警告的真正含义。

    有些编译器将警告设置为错误,能使得开发者更加认真的对待警告。
    一个团队之间需要统一警告和错误的标准

    (6) 调试器:断点
    ▪ 调试器是使程序员能够监视程序的执行、停止程序、重新启动程序、设置断点和更改内存中的值的软件工具。
    ▪ 单步执行源代码-断点-单步执行-恢复操作-临时断点
    ▪ 检查变量
    ▪ 发布“所有点公告”以更改变量–监视点结合了断点和变量检查的概念。
    ▪ 在调用堆栈上下移动

    ▪ 继续执行-继续调试器将运行到下一个断点并暂停。
    ▪ 调试一步一步地进行–步骤转移将只执行行并转到下一行。如果一个方法将在这一行中被调用,调试器将不会调试到该方法的代码中,并将该方法作为一个完整的步骤完全执行。
    –Step Into将只执行行并转到下一行。如果在这一行中要调用一个方法,下一步是进入该方法并继续逐步调试。
    –Step Return如果调试器正在一步一步地调试方法,“Step Return”将允许调试器运行整个方法(直到该方法结束),直到它作为一个完整步骤返回为止。
    ▪ 观察点结合了断点和变量检查的概念。
    ▪ 最基本的形式指示调试器在指定变量的值发生更改时暂停程序的执行。▪ Eclipse中的条件断点:

    展开全文
  • 测试一个FIFO 1、编译并仿真 vcs -debug -f run1.f simv 仿真结果出现错误 Read 4444 from FIFO FAILURE: Empty flag missed at time 250000000000.000 ps....time = 260000000000.000 ps $finish called from file ...
  • debugging Problem

    2019-07-17 14:16:24
    参考网址: ...Number=14648&PHPSESSID=2e3c1b028a66500ae8a1730abc88b993 在开发项目的过程中,遇到一个比较比较奇怪的问题,当在过程中声明一个varcha...
  • [Qt]Cannot retrieve debugging output

    万次阅读 多人点赞 2013-05-27 09:17:28
    描述: Qt Creator的问题,两个IDE同时打开,后打开的会出现这个情况 解决方案: 只打开一个IDE。
  • Debugging Tools for Windows (WinDbg)的使用

    万次阅读 2017-04-11 09:31:58
    Debugging Tools for Windows (WinDbg)的使用
  • VS code 调试 unable to start debugging

    万次阅读 2019-05-31 17:23:41
    解决方法:
  • 环境: arm-linux, kernel3.2.0,...Disabling lock debugging due to kernel taint 在网上收到的解决方案是增加 MODULE_LICENSE("GPL");语句。但是实际上我已经添加了。 如果把MODULE_LICENSE("GPL");删
  • Qt Creator 3.5.1(Qt4.8.4库+MinGW4.4)下使用minGW4.4...Debugging starts Debugging has failed Debugging has finished 原因:Qt Creator 3.5.1需要更新版本的GDB。从http://qt-project.org/wiki/QtCreato
  • 使用VScode 调试的时候提示Unable to start debugging. Launch options string provided by the project system is invalid. Unable to determine path to debugger. Please specify the "MIDebuggerPath"...
  • 代码已经可以运行成功 但是调试会报错 最后发现是因为路径中有中文
  • gdb调试(no debugging symbols found)

    万次阅读 2009-11-09 23:11:00
    gdb 调试程序时出现下面信息: GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU
  • 微软将此工具集成到WDK上面,如果下载WDK完整安装包的话,需要下载600m多的文件,显然这是不必要的,如果我们去其他网站上面下载很可能下载到旧的版本,我们只需要下载WDK的在线安装版本即可,安装的时候把其他复选框...
  • 用pl/sql developer 调试...错误信息:debugging requires the debug connect session system privilege. 原因:用户权限不够,使用以下命令授予权限: GRANT debug any procedure, debug connect session TO scott
  • 程序又崩溃了,使用gdb加载一看: ...Reading symbols from gh_manager...(no debugging symbols found)...done.  这是什么意思?查了一下,编译时:  要有-g选项,  同时,不能有-s选项.  ...
  • windbg (Debugging Tools for Windows)

    千次下载 热门讨论 2020-07-30 23:32:40
    微软Debugging Tools for Windows工具,简称windbg,查看dmp文件,调试驱动程序、应用程序等。 资源中有两个文件:64位系统6.12版本和32位系统6.11版本 The Debugging Tools for Windows can be used to help you ...
  • 最近在用debug方式启动idea的时候IDE 一直提示这个问题,启动的特别慢,后来查了一下才发现原来是在方法上面添加断点啦 去掉该断点一下就一切正常啦!
  • 如果用QtCreator开发软件,调试环境没配置好会出现,在debug的时候会出现Unable to create a debugging engine,之前在windows平台使用解决方案很多,网上的答案也是一大堆。Linux下的答案比较少,像unbuntu, deepin...
1 2 3 4 5 ... 20
收藏数 116,956
精华内容 46,782
关键字:

debugging