Xcode GDB 调试

Xcode GDB 调试,第1张

概述关于GDB 对于大多数Cocoa程序员来说,最常用的debugger莫过于Xcode自带的调试工具了。而实际上,它正是gdb的一个图形化包装。相对于gdb,图形化带来了很多便利,但同时也缺少了一些重要功能。而且在某些情况下,gdb反而更加方便。因此,学习gdb,了解一下幕后的实质,也是有必要的。 gdb可以通过终端运行,也可以在Xcode的控制台调用命令。本文将通过终端讲述一些gdb的基本命令和技 关于GDB

对于大多数Cocoa程序员来说,最常用的deBUGger莫过于Xcode自带的调试工具了。而实际上,它正是gdb的一个图形化包装。相对于gdb,图形化带来了很多便利,但同时也缺少了一些重要功能。而且在某些情况下,gdb反而更加方便。因此,学习gdb,了解一下幕后的实质,也是有必要的。

gdb可以通过终端运行,也可以在Xcode的控制台调用命令。本文将通过终端讲述一些gdb的基本命令和技巧。

首先,我们来看一个例子:

    #import <Foundation/Foundation.h> 

    int main(int argc,char **argv) 
    
        NSautoreleasePool *pool = [[NSautoreleasePool alloc] init]; 
        NSLog(@"Hello,world!"); 
        [pool release]; 

        return 0; 
    }

我们把文件命名为test.m,然后编译:

    gcc -g -framework Foundation test.m

准备工作已经完成。现在我们可以开始调试了。只要把要调试的文件名作为参数,启动gdb:

    gdb a.out

gdb启动后会输出很多法律声明之类的信息。无视它们,最后我们看到一个提示

    (gdb)

成功!现在deBUGger和刚才编译好的程序都被装载了。不过,现在程序还没有开始运行。因为gdb在程序开始前把它暂停了,好让我们有机会设置调试参数。这次我们不需要做特别设置,所以马上开始运行吧:

    (gdb) run 

    Starting program: /Users/mikeash/shell/a.out 
    Reading symbols for shared librarIEs .++++....................... done 
    2011-06-16 20:28:53.658 a.out[2946:a0f] Hello,world! 

    Program exited normally. 
    (gdb)

糟糕,程序竟然exited normally了(==|||)。这可不行,我们得让他崩溃才行。所以我们给这个小程序添加一个BUG:

    int x = 42; 
    NSLog("Hello,world! x = %@",x);
nice。这样一来程序就会漂亮地崩溃了:

    (gdb) run 

    Starting program: /Users/mikeash/shell/a.out 
    Reading symbols for shared librarIEs .++++....................... done 

    Program received signal EXC_BAD_ACCESS,Could not access memory. 
    Reason: 13 at address: 0x0000000000000000 
    0x00007fff84f1011c in objc_msgSend () 
    (gdb)

如果我们是在shell中直接运行的程序,在崩溃后就会回到shell。不过现在我们是通过gdb运行的,所以现在并没有跳出。gdb暂停了我们的程序,但依然使之驻留在内存中,让我们有机会做调试。

首先,我们想知道具体是哪里导致了程序崩溃。gdb已经通过刚才的输出告知了我们: 函数objc_msgSend就是祸之根源。但是这个信息并不足够,因为这个objc_msgSend是objc运行时库中的函数。我们并不知道它是怎么调用的。我们关注的是我们自己的代码
要知道这一点,我们需要得到当前进程的函数调用栈的情况,以此回溯找到我们自己的方法。这时我们需要用到backtrace命令,一般简写为bt:

    (gdb) bt 
    #0 0x00007fff84f1011c in objc_msgSend () 
    #1 0x00007fff864ff30b in _CFStringAppendFormatandArgumentsAux () 
    #2 0x00007fff864ff27d in _CFStringCreateWithFormatAndArgumentsAux () 
    #3 0x00007fff8657e9ef in _CFLogvEx () 
    #4 0x00007fff87beab3e in NSLogv () 
    #5 0x00007fff87beaad6 in NSLog () 
    #6 0x0000000100000ed7 in main () at test.m:10

现在我们可以看到,程序在test.m的第10行,调用NSLog方法时崩溃了。接下来我们想看一下这次调用的详细信息。这时我们要用到up命令。up命令可以在栈的各层之间跳转。本例中,我们的代码main是#6:

    (gdb) up 6 
    #6 0x0000000100000ed7 in main () at test.m:10 
          NSLog("Hello,x);
这回不仅是函数名,连出错的那行代码也打印出来了。但是,我们还可以使用List(简写为l)命令,打印出更多信息:
ps: 如果需要回到栈列表。可以使用down命令。

    (gdb) l 
      
      int main(int argc,char **argv) 
      { 
          NSautoreleasePool *pool = [[NSautoreleasePool alloc] init]; 
          int x = 42; 
  
总结

以上是内存溢出为你收集整理的Xcode GDB 调试全部内容,希望文章能够帮你解决Xcode GDB 调试所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1064892.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-26
下一篇2022-05-26

发表评论

登录后才能评论

评论列表(0条)

    保存