iOS陆先森开发随笔(三)iOS调试技巧(debug)

      说到debug,可以说到的东西就太多了,一个程序员,即使逻辑非常出色,也会出现bug问题,那么debug是每个程序员必备的技巧,尤其是Xcode开发,苹果公司的开发的Xcode真的是十分强大,debug可以通过控制台,友盟,问题的异常抛出,等很多方法找出,发现bug
那么开始我们的debug。
    调试技巧一、po命令
    不要说你不会po命令,假如不会,那就太菜了。

    在卡住断点的时候可以利用po来输出你想看到的东西,陆哥要截图了



如上所述,po的含义为print object-c的意思,为显示对象的文本描述,显示对象的description
    图片中的<nil>就是变量rowindex的值。
 
    调试技巧二、help命令
     当你忘记某条gbd命令的语法时,可以使用help命令来获取帮助信息。如:help show 显示show命令语法。

    (gdb) help show
    Generic command for showing things about the debugger.
     
    List of show subcommands:
     
    show annotate -- Show annotation_level
    show architecture -- Show architecture of target
    show args -- Show argument list to give program being debugged when it is started
    show arm -- Various ARM-specific commands
    show auto-raise-load-levels -- Show if GDB should raise the symbol loading level on all frames found in backtraces
    show auto-solib-add -- Show autoloading of shared library symbols
    show backtrace -- Show backtrace specific variables
    show breakpoint -- Breakpoint specific settings
    show can-use-hw-watchpoints -- Show debugger's willingness to use watchpoint hardware
    show case-sensitive -- Show case sensitivity in name search 

    调试技巧三、print命令
    类似于格式化输出
    
(gdb) print (int)[str retainCount]  

    $1 = 2  

    
    
调试技巧四、断点设置异常抛出
     
有时候我们的程序不知道跑到哪个地方就 crash 了,而 crash 又很难重现。保守的做法是在系统抛出异常之前设置断点,具体来说是在 objc_exception_throw处设置断点。设置步骤为:首先在 XCode 按 CMD + 6,进入断点管理窗口;然后点击右下方的 +,增加新的 Symbolic Breakpoint,在 Symbol 一栏输入:objc_exception_throw,然后点击 done,完成。 这样在 Debug 模式下,如果程序即将抛出异常,就能在抛出异常处中断了。比如在前面的代码中,我让 [firstObjctcrashTest]; 抛出异常。在 objc_exception_throw 处设置断点之后,程序就能在该代码处中断了,我们从而知道代码在什么地方出问题了。



调试技巧5、程序调试时忽然崩溃,而找不到崩溃的代码,如何解决?
 
在Edit-->Scheme里面 找到Arguments把下面3个值设置成YES
NSAutoreleaseFreedObjectCheckEnabled 
NSZombleEnabled
NSDebugEnabled 
一个很不错的方法,建议在建立工程的时候,加入此设置 



出现 EXC_BAD_ACCESS  错误,给你的错误提示就这个,如何根本没法知道哪里错误了,其实还是有方法知道的,

做如下设置:
Project -> Edit active executable ->Argument 
添加如下四个参数
NSDebugEnabled
NSZombieEnabled
MallocStackLogging 
MallocStackLoggingNoCompact
并都设置为YES。具体如下图:

这个时候,如果有如下一段代码:
 //重复释放一个变量 
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  NSData* data = [NSData dataWithBytes:"asklaskdxjgr" length:12];
  [data release];
  [pool release];
再Debug窗口会有如下的提示

虽然也能大致判断是哪种类型的变量重复释放了,但信息还不够多,当项目大,源码比较多的时候,也不太方便定位,

在console窗口运行如下命令可以得到更多信息:shell malloc_history <pid> <address>"
 输入命令:shell malloc_history3939 0xa4e10
 就会出现更多的信息:
  [dave@host193 Frameworks]$ malloc_history 3939 0xa4e10
  Call [2] [arg=32]: thread_a0000dec |0x1000 | start | _start | main |
  +[NSData dataWithBytes:length:] | NSAllocateObject | object_getIndexedIvars |
  malloc_zone_calloc  
这个时候就知道具体哪个函数出先问题了,从这里可以看到main里NSData出现问题了。 
 
2. NSArray等集合类的实用问题。
      如下面的代码    
        ReleaseTest* rt = [[alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] init] ;
[array addObject: rt];
ReleaseTest *rt2 = [array objectAtIndex:0];
      [rt2 release];   
[array release];
[rt release]; 
     就会导致重复释放内存问题,因为rt2,获取的是一个对象的指针,如果已经释放了的话,rt在释放的话,就重复了,为了遵循谁Init谁Release的原则,rt2就不应该Release。
 
3. init 和 Release 的问题。
    凡是对象通过Init的方法生成的对象,都需要自己负责Release。
    凡不是通过Init的方法生成的对象,不需要负责Release.如[NSString StringWithFormat]方法生成的对象就不需要自己Release,因此自己定义函数,返回一个类的时候,一定要设置为autoRelease 。这样调用的人就不用操心是否需要释放对象了。
 4. AutoReleasePool里最好不要将AutoRelease对象赋值给其它对象,否则离开这个作用域后,对象将会Release掉。

    这是一篇简单的debug的文章,细心的同学可能发现,陆哥的Xcode怎么是5.1.1的开发环境,系统貌似也是10.9.2 一下的,文章是以前写的,然后做的总结,现在拿出来发表一下博客,希望有助于新手学习,当时公司的电脑是Xcode6.1的,家里的pro和air都没有升级,回来就是看看书学学习什么的,也就没有升级,但是开发的同学要注意了~!!!苹果去年8月分要求全部的软件必须兼容iOS8,否则就给你产品下架,那么说明了什么~你的操作系统必须是最新的,Xcode必须时6.1以上的,相信大家已经知道Xcode废掉了一些老的sdk,还有很多新的东西,希望大家多多学习。
    下面一篇debug文章是同事大哥写的,感觉太好了~!!!(真心赞~
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章