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文章是同事大哥寫的,感覺太好了~!!!(真心贊~
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章