iOS中的崩溃类型

http://blog.csdn.net/womendeaiwoming/article/details/44243571

在实际编制程序中,会日常遇上多少个类中的某个方法实现逻辑类似的情况,这时大家得以将那些类中的相同部分虚幻到父类中,对于有出入的地点,子类依照自身的莫过于要求来分别达成。

OS中的崩溃类型

以羽球运动为例,打球必有发接发环节,发球分正手和反手三种(那里不探讨羽毛球类技巧术细节),一般男子双打反手发球,女子单打正手发球,但发接发那些环节的流水生产线是如出一辙的。

      
在那边询问一下XCode用来表示各个崩溃类型的术语,补充部分那下面的各文化。崩溃平常是指操作系统向正在运作的次序发送的信号,所以大家在查看崩溃日志时,经常见到如下错误摘要:Application
received signal SIGSEGV。一般的话,常见的倒台类型有以下两种:

澳门葡京集团网站 1

 

 

1、        EXC_BAD_ACCESS

abstract class Badminton
{
    public abstract void Serve();

    public abstract void Catch();

    public abstract void Play();
}

class MenSingle : Badminton
{
    public override void Serve()
    {
        Console.WriteLine("反手发球......");
    }

    public override void Catch()
    {
        Console.WriteLine("正手推底线");
    }

    public override void Play()
    {
        Serve();
        Catch();
    }
}


class WomenSingle : Badminton
{
    public override void Serve()
    {
        Console.WriteLine("正手发球.......");
    }

    public override void Catch()
    {
        Console.WriteLine("软压一拍");
    }

    public override void Play()
    {
        Serve();
        Catch();
    }
}

   
   在拜访贰个业已放出的靶子或向它发送音信时,EXC_BAD_ACCESS就会并发。造成EXC_BAD_ACCESS最广大的缘由是,在初步化方法中起初化变量时用错了全数权修饰符,那会造成对象太早地被放飞。举个例子,在viewDidLoad方法中为UIViewController创设了二个富含成分的NSArray,却将该数组的全数权修饰符设成了assign而不是strong。现在在view威尔Appear中,若要访问已经刑释掉的对象时,就会拿走名为EXC_BAD_ACCESS的崩溃。

 

      
那些崩溃发生时,查看崩溃日志,却屡屡得不到有用的栈消息。幸亏,有2个艺术用来解决这一个标题:NSZombieEnabled。

程序开发中有个关键的尺码:Don't repeat yourself。而地方一段代码中,子类MenSingleWomenSingle中的Play办法是重新的,羽球运动除男子双打、女子双打外还有男子双打,女子双打,男女混合双打,如此则代码中最少五处重复,这分明不方便人民群众日后维护。
接下去对代码举行核对:

      
那是一个环境变量,用来调节与内部存款和储蓄器相关的难点,跟踪对象的放出进度。启用了NSZombieEnabled的话,它会用二个僵尸达成来去你的私下认可的dealloc实现,也正是在引用计数降到0时,该僵尸实现会将该指标转换到僵尸对象。僵尸对象的功用是在你向它发送消息时,它会显得一段日志并活动跳入调节和测试器。

abstract class Badminton
{
    protected abstract void Serve();

    protected abstract void Catch();

    public void Play()
    {
        Serve();
        Catch();
    }
}

class MenSingle : Badminton
{
    protected override void Serve()
    {
        Console.WriteLine("反手发球......");
    }

    protected override void Catch()
    {
        Console.WriteLine("正手推底线");
    }

}


class WomenSingle : Badminton
{
    protected override void Serve()
    {
        Console.WriteLine("正手发球.......");
    }

    protected override void Catch()
    {
        Console.WriteLine("软压一拍");
    }

}

      
所以,当在选取中启用NSZombie而不是让使用直接崩溃时,1个谬误的内部存款和储蓄器访问就会成为一条不能辨认的音信发送给僵尸对象。僵尸对象会议及展览示接收到的消息,然后跳入调节和测试器,那样你就能够查阅究竟哪时出了难题。

 

      
能够在Xcode的scheme页面中设置NSZombieEnabled环境变量。点击Product-à艾德it
Scheme打开该页面,然后勾选Enable Zombie Objects复选框,如图所示:

那段代码将Play艺术放到父类中落实,对于有差别的ServeCatch则交有子类达成,那边是模板方法情势,封装不变部分,扩充可变部分。当中Play格局称之为模板方法,ServeCatch何谓基本情势。
通常模板方法(能够有多个)在父类中落实并调用基本方法以完结一定的逻辑,且不容许子类重写。
主干格局貌似为架空方法,由子类来实现具体的贯彻。基本格局的拜访修饰符平时是protected,不供给对外场展露(迪米特法则),客户端只须求调用模板方法即可。

 

那正是说,难题来了,世界羽球联合会没有分明男子单打必须用反手发球,女子双打必须正手发球。固然男双想用正手发球如何做?为适应那种具有各个只怕的场合,大家对代码稍作调整:

 澳门葡京集团网站 2

abstract class Badminton
{
    private  void ForehandServe()
    {
        Console.WriteLine("正手发球.......");
    }

    private void BackhandServe()
    {
        Console.WriteLine("反手发球......");
    }

    protected abstract void Catch();

    protected abstract bool IsForeHandServe { get; }

    public void Play()
    {
        if (IsForeHandServe)
        {
            ForehandServe();
        }
        else
        {
            BackhandServe();
        }
        Catch();
    }
}

class MenSingle : Badminton
{
    protected override bool IsForeHandServe => false;

    protected override void Catch()
    {
        Console.WriteLine("正手推底线");
    }
}


class WomenSingle : Badminton
{
    protected override bool IsForeHandServe => true;

    protected override void Catch()
    {
        Console.WriteLine("软压一拍");
    }
}

      
僵尸在RAC出现在此之前功能非常大。但自从有了ASportageC,固然您在目的的全部权方面可比小心,那么普通不会境遇内部存款和储蓄器相关的夭亡。

 

 

此间,我们经过在子类中完结属性IsForehandServe来控制父类中实际调用ForehandServe措施也许调用BackhandServe方法。属性IsForehandServe何谓钩子函数,根据钩子函数的不等完毕,模板方法可以有两样的施行结果,即子类对父类产生了震慑。

2、        SIGSEGV

如上,是三个模板方法的杜撰使用境况。模板方法形式有个很关键的天性:父类控制流程,子类负责具体细节的实现。这里有没有联想到IoC(控制反转)?IoC的实现格局有种种,DI只是中间之一,模板方法方式也能够。

   
   段错误音信(SIGSEGV)是操作系统一发布生的三个更要紧的难点。当硬件现身错误、访问不可读的内部存款和储蓄器地址或向受保险的内部存款和储蓄器地址写入数据时,就会发生那几个漏洞非常多。

无数框架(如:ASP.NET
MVC)也是其一套路,框架定义一套流程,然后由分歧的类负责不相同作用的兑现,并留下扩充点让开发职员可依照实际需要举行扩张开发,但整个框架的处理流程开发人士是控制不了的。

   
   硬件错误这一情景并不普遍。当要读取保存在RAM中的数据,而该职位的RAM硬件不符合规律时,你会收到SIGSEGV。SIGSEGV越来越多是出现在后二种情状。暗中同意情状下,代码页不一致意开始展览写操作,而数据而不允许进行实施操作。当使用中的有些指针指向代码页并总括修改指向地方的值时,你会接受SIGSEGV。当要读取多少个指南针的值,而它被早先化成指向无效内部存款和储蓄器地址的垃圾值时,你也会吸收SIGSEGV。

小结

模板方法格局有以下优点:
一 、封装不变部分,扩充可变部分;

写程序就因该是那样,不仅仅是在模板方法情势中

② 、提取公共部分方便人民群众日后保险;

Ctrl + C,Ctrl + V 大法好,但滥用也是极度的

叁 、父类控制流程,子类负责落到实处;

那样,子类便可透过扩张的措施来充实际效果益;
与此同时,对于有些复杂的算法,大家能够前几天父类的模版方法中定义好流程,然后再在子类中去达成,思路上也会清楚不少;

   
   SIGSEGV错误调节和测试起来更辛勤,而致使SIGSEGV的最普遍原因是不科学的类型转换。要防止过度使用指针或尝试手动修改指针来读取私有数据结构。假诺您那么做了,而在修改指针时不曾注意内存对齐和填充难题,就会吸收接纳SIGSEGV。

结语

终极,附一段使用模板方法方式写的分页查询代码:

public class DbBase
{
    public virtual string TableName
    {
        get
        {
            throw new NotImplementedException($"属性:{nameof(TableName)}不得为空!");
        }
    }

    protected virtual string ConnectionString
    {
        get
        {
            throw new NotImplementedException("属性:" + nameof(ConnectionString) + "不得为空!");
        }
    }

    protected SqlConnection CreateSqlConnection()
    {
        return CreateSqlConnection(ConnectionString);
    }

    protected SqlConnection CreateSqlConnection(string connnectionString)
    {
        SqlConnection dbConnection = new SqlConnection(connnectionString);
        if (dbConnection.State == ConnectionState.Closed)
        {
            dbConnection.Open();
        }
        return dbConnection;
    }

 

public interface IPagingQuery<T>
    where T : class
{
    /// <summary>
    /// 数据总量
    /// </summary>
    int DataCount { get; }

    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="pageNumber">页码</param>
    /// <param name="pageSize">每页数据量</param>
    /// <returns></returns>
    IEnumerable<T> PagingQuery(int pageNumber, int pageSize);
}

public abstract class PagingQueryDalBase<T> : DbBase, IPagingQuery<T>
    where T : class
{
    public int DataCount => GetDataCount();

    /// <summary>
    /// 查询数据总数SQL
    /// </summary>
    protected abstract string QueryDataCountSql();

    private int GetDataCount()
    {
        int dataCount;
        using (SqlConnection sqlConnection = base.CreateSqlConnection())
        {
            string sql = QueryDataCountSql();
            dataCount = sqlConnection.QueryFirstOrDefault<int>(sql);
        }
        return dataCount;
    }

    /// <summary>
    /// 分页查询SQL
    /// </summary>
    protected abstract string PagingQuerySql(int pageNumber, int pageSize);

    public IEnumerable<T> PagingQuery(int pageNumber, int pageSize)
    {
        if (pageNumber - 1 < 0)
        {
            throw new ArgumentException("参数:pageNumber不得小于1");
        }

        if (pageSize <= 0)
        {
            throw new ArgumentException("参数:pageNumber必须大于0");
        }
        IEnumerable<T> result;
        using (SqlConnection sqlConnection = CreateSqlConnection())
        {
            string sql = PagingQuerySql(pageNumber, pageSize);
            result = sqlConnection.Query<T>(sql);
        }
        return result;
    }
}

 

 

版权注解

正文为小编原创,版权归小编雪飞鸿享有。
转发必须保留作品的完整性,且在页面明显地点处标明原稿链接

如非凡, 请发送邮件和笔者联系。

3、        SIGBUS

   
   总线错误信号(SIGBUG)代表无效内部存款和储蓄器访问,即访问的内部存储器是3个不行的内部存款和储蓄器地址。也正是说,那些地点指向的职分根本不是情理内部存款和储蓄器地址(它大概是某个硬件芯片的地址)。SIGSEGV和SIGBUS都羽球EXC_BAD_ACCESS的子类型。

 

4、        SIGTRAP

   
   SIGTRAP代表陷阱信号。它并不是四个真的的垮台信号。它会在电脑执行trap指令发送。LLDB调节和测试器平日会处理此信号,并在内定的断点处结束运行。假使您接到了缘由不明的SIGTRAP,先祛除上次的输出,然后重新展开创设日常能一蹴即至这几个题材。

 

5、        EXC_ARITHETIC

   
   当要除零时,应用会收到EXC_AQashqaiITHMETIC信号。那一个漏洞非常多应该很不难消除。

 

6、        SIGILL

       SIGILL代表signal illegal
instruction(违规命令信号)。当在电脑上推行非法命令时,它就会发生。执行违法命令是指,将函数指针会给此外贰个函数时,该函数指针由于某种原因是坏的,指向了一段一度出狱的内部存款和储蓄器或是四个数据段。有时你收到的是EXC_BAD_澳门葡京集团网站,INSTRUCTION而不是SIGILL,就算它们是3遍事,不过EXC_*相同此信号不依靠种类布局。

 

7、        SIGABRT

       SIGAB大切诺基T代表SIGNAL
ABO纳瓦拉T(中止信号)。当操作系统一发布现不安全的景况时,它亦可对那种情况开展愈来愈多的支配;须要的话,它能要求进程展开清理工科作。在调节和测试造成此信号的底部错误时,并不曾什么妙计。Cocos2d或UIKit等框架日常会在一定的前提条件没有满足或部分不佳的状态出现时调用C函数abort(由它来发送此信号)。当SIGABKoleosT出现时,控制台平日会输出大量的音讯,表明具体哪里出错了。由于它是可决定的崩溃,所以能够在LLDB控制台上键入bt命令打字与印刷出回溯消息。

 

⑧ 、        看门狗超时

   
   那种崩溃平常比较便于辨别,因为错误码是原则性的0x8badf00d。(程序员也有有趣的一派,他们把它读作Ate
Bad
Food。)在iOS上,它日常出现在实践一个体协会同网络调用而围堵主线程的动静。因而,永远不要开始展览协同网络调用。