概述对于大多数Cocoa程序员来说,最常用的debugger莫过于Xcode自带的
调试工具了。而实际上,它正是gdb的一个图形化包装。相对于gdb,图形化带来了很多便利,但同时也缺少了一些重要功能。而且在某些情况下,gdb反而更加方便。因此,学习gdb,了解一下幕后的实质,也是有必要的。 gdb可以通过终端运行,也可以在Xcode的控制台调用命令。本文将通过终端讲述一些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. 糟糕,程序竟然exited normally了(==|||)。这可不行,我们得让他崩溃才行。所以我们给这个小程序添加一个BUG:
int x = 42; NSLog("Hello,world! x = %@",x);
nice。这样一来程序就会漂亮地崩溃了:
Program received signal EXC_BAD_ACCESS,Could not access memory. Reason: 13 at address: 0x0000000000000000 0x00007fff84f1011c in objc_msgSend () 如果我们是在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 9 NSLog("Hello,sans-serif; Font-size:14px; line-height:24px; text-align:left">这回不仅是函数名,连出错的那行代码也打印出来了。但是,我们还可以使用List(简写为l)命令,打印出更多信息:
ps: 如果需要回到栈列表。可以使用down命令。
(gdb) l 5 6 int main(int argc,sans-serif; Font-size:14px; line-height:24px; text-align:left">7 { 8 NSautoreleasePool *pool = [[NSautoreleasePool alloc] init]; int x = 42;
总结
以上是内存溢出为你收集整理的XCode中gdb调试技巧全部内容,希望文章能够帮你解决XCode中gdb调试技巧所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
评论列表(0条)