为Objective-C编程调试技巧(译)

http://www.cocoawithlove.com/2008/10/debugging-tips-for-objective-c.html

这篇文章是关于从程序获得额外的信息在运行时。Xcode和GDB都支持广泛的信息获取工具 - 但你需要知道,他们在那里。下面是一些Objective-C的具体gdb的提示和指令,所有的Cocoa程序员应该知道的。

说话直接用gdb

调试器控制台窗口很聊得来的gdb的方式。从运行菜单(或type命令移-R)显示在Xcode的控制台窗口。

您只能发送命令到GDB当程序暂停(停止在断点处)。当你有(GDB)提示,然后你可以跟gdb调试程序。

大多数命令,gdb的接受,Xcode的通过显示在调试器窗口中的值会自动为你处理。所以我打算忽略其中的大多数。

"po":打印对象

打印对象命令显示一个Objective-C的对象的文本表示。

想象一下,你想知道为什么你的电话:

- (ID )getFirstObjectFrom:(NSDictionary中 *)stringDictionary
{
    返回 [stringDictionary objectForKey @“FIRSTKEY” ];
}

将返回零。设置就行了断点,当调试器停止在这一点上,进入调试器控制台,然后键入:

po   stringDictionary

命中回报和gdb会给出结果。就我而言,它是:

{
    FIRSTKEY = firstObject;
    secondKey = secondObject;
    thirdKey = thirdObject;
}

我应该使用的键名是@“FIRSTKEY”以小写'F'。问题解决了。

在这种情况下,gdb的被调用描述的方法的NSDictionary生成的字符串。该描述方法用于所有的整个可可来生成对象的字符串,你可以重写它,以提供您的对象的字符串表示形式。

Xcode的数据格式化

如果调试器仍然停在同一条线上,你在Xcode打开调试器窗口,变量的“参数”列表将包含一个条目stringDictionary。对于一个的NSDictionary这样的对象,Xcode中会显示在“摘要”栏“3键/值对。”

此信息来自一个“数据格式化”,也就是设立的NSDictionary默认。你可以了解他们在苹果的Xcode调试指南:使用数据格式化。从本质上讲,数据格式化告诉Xcode中如何获取一些数据在列中显示。

不同的数据格式可以看出,如果我们在右键单击stringDictionary行中的调试器窗口,然后从上下文菜单中选择“打印说明以控制台”。

打印 的说明 stringDictionary
< CFDictionary 0 x 3 5 EDD 0 [ 0 XA 0 b 0 6 1 7 4 ]> {类型=不变,计数= 3 ,容量= 3 ,对=(
    0 :< CFString字符串 0 x 2 0 9 0 [ 0 XA 0 b 0 6 1 7 4 ]> {内容=“secondKey”} = < CFString字符串 0 x 2 0 8 0 [ 0 XA 0 b 0 6 1 7 4 ]> {内容=“secondObject”}
    1 :< CFString字符串 0 x 2 0 b 0 [ 0 XA 0 b 0 6 1 7 4 ]> {内容=“thirdKey”} = < CFString字符串 0 x 2 0 0 [ 0 XA 0 b 0 6 1 7 4 ]> {内容=“thirdObject”}
    3 :< CFString字符串 0 x 2 0 7 0 [ 0 XA 0 b 0 6 1 7 4 ]> {内容=“FIRSTKEY”} = < CFString字符串 0 x 2 0 6 0 [ 0 XA 0 b 0 6 1 7 4 ]> {内容=“firstObject”}
)}

如果没有数据格式,“打印说明以控制台”将输出相同的信息为“宝”命令。在这种情况下,虽然,它清楚地输出一个更详细的描述的字典,具有完整的类型信息和索引。正是这个CFDictionary数据格式化驻留是未知的我(它不是在为Xcode中的数据格式化的标准位置)。

其他的“打印”命令

该PO在gdb的命令永远只能显示结果从调用描述一个物体上,但更普遍的打印命令将让我们做其他事情。

我可以使用下面的命令:

打印(字符*)[[stringDictionary 描述] 的CString ]

这将有输出:

$ 1 = 0 x 3 6 0 0 3 1 “{\ñFIRSTKEY = firstObject; \ñsecondKey = secondObject; \ n
    thirdKey = thirdObject; \ n}的“

这是相同的数据表示为宝为例,减去漂亮的格式。

我还可以使用下面的命令:

打印(整型)[stringDictionary retainCount ]

制定出的保留计数stringDictionary帮我工作了,为什么内存或者是没有得到释放。

由于与PO命令和“打印说明以控制台”在Xcode相等,则打印命令有一个Xcode的等价了。您可以从运行- >显示- >表达式菜单打开表达式窗口。

“信息符号”:得到一个地址的符号名

最后的gdb命令我要在这里讨论的是信息符号的地址,返回与给定的存储单元关联的任何变量或代码的名称地址

想象一下,例如,你的内存地址“混淆0xa0b06174通过“打印说明到控制台”输出显示“stringDictionary那我上面显示。所有您需要做的则是类型:

信息符号0 XA 0 b 0 6 1 7 4

进入调试器控制台和gdb会告诉你:

__kCFAllocatorSystemDefault 部分LC_SEGMENT 。__DATA 。__data 的/系统/库/框架/的CoreFoundation 。框架/版本/ A /的CoreFoundation

这是系统默认的CoreFoundation内存分配器。也许这还并不意味着一大堆,但至少我们知道在该地址中声明的对象的名称。

当你得到一个异常日志,看起来像这样更加有用的是:

2 0 0 8 - 1 0 - 2 6 13 2 5 4 3 .381 CrashExample [ 4 1 7 2 0 2 0 B] *** - [ TransitionView doesntExist ]:无法识别的选择发送到实例0 XF 4 FBB 0
2 0 0 8 - 1 0 - 2 6 13 2 5 4 3 0.383 CrashExample [ 4 1 7 2 0 2 0 B] *** 终止 应用程序因未捕获的异常'NSInvalidArgumentException', 原因:'*** - [ TransitionView doesntExist ]:无法识别的选择发送到实例0 XF 4 FBB 0 '
2 0 0 8 - 1 0 - 2 6 13 2 5 4 3 .385 CrashExample [ 4 1 7 2 0 2 0 B] 堆栈:(
    2 5 2 8 0 1 3 8 0 4
    2 4 7 8 5 0 3 1 4 8
    2 5 2 8 0 4 2 9 2 0
    2 5 2 8 0 3 6 2 7 2
    2 5 2 8 0 3 6 9 2 0
    1 1 0 7 6
    1 1 8 8 0
    8 1 6 1 7 4 8 8 0
    8 1 6 1 7 4 8 8 0
    8 1 6 5 0 4 0 3 6
    8 1 6 5 0 0 9 6 0
    8 1 6 2 5 8 7 9 2
    8 1 6 2 0 2 1 2 8
    8 1 6 1 9 9 5 0 8
    8 2 9 0 0 5 5 2 0
    8 2 9 0 1 4 7 7 2
    2 5 2 7 5 6 4 4 5 6
    8 2 9 0 0 7 7 2 4
    8 1 6 1 7 3 0 1 6
    8 1 6 2 1 2 3 3 6
    9 8 8 8
    9 6 6 8

日志告诉我们发生了,因为一个无法识别的选择发送到一个对象,但我们可能不知道在这个程序中发生的问题。

你可以看一下堆栈跟踪,看到的最高地址是“小”(即可能是在你的代码,而不是默认的库)为“11076”,然后给gdb的命令:

信息符号1 1 0 7 6

和gdb会告诉你:

- [ CrashExampleAppDelegate performTransition ] + 8 8 部分LC_SEGMENT 。__TEXT 。__text 的/用户/哑光/项目/ CrashExample 。应用程序/ CrashExample

它告诉我们,这个问题发生在方法performTransition。

更新:由于在评论中指出的“G”,还有一个更好的方法来确定的方法和代码行的在这种情况下一个地址。信息行* 11076会以原始的源代码文件中的行,而不仅仅是字节从函数的起始偏移量。

这使得它烦人,在Mac OS X 10.5 -如果你看看5上面的地址列表中的11076,他们都与抛出异常本身相关联objc_exception_throw只返回前5名地址,因为这5个地址往往是相同的异常抛出地址(他们不说任何事情,为什么抛出异常)。

地址和符号调试器外

既然我提到坠毁阅读文件和查看内存地址:GDB不这样做,如果最好的方法别人给你的内存地址。要做到这一点,你应该从他们所使用的确切构建有。的dSYM文件。

如果你不知道如何生成。的dSYM文件,转到项目 - >编辑项目设置 - >生成 - >生成选项 - >调试信息格式,并确保你有一个的dSYM文件。你应该保留这些文件大约为每个建立你释放。iPhone SDK的默认生成这些文件,但您将需要打开的手动上为Mac版本。

调用的命令行如下:

dwarfdump-A的<em> NameOfdSYMFile </ em>的

这会告诉你该文件中的每一知道地址。所有您需要做的是找到最接近上述任一地址到您崩溃的位置,这将是罪魁祸首方法或函数。

然而,这是一个非常笨拙的方法。为了得到一次单一的地址,将。的dSYM和。的应用程序,它是指在同一目录下,你可以使用ATOS命令可以获得一个地址一个符号。上面显示的CrashExample崩溃的bug,你可以调用这个命令是这样的:

ATOS-O CrashExample 。应用程序/内容/的MacOS / CrashExample 拱PPC 1 1 0 7 6

这将使结果:

- [ CrashExampleAppDelegate performTransition ]( CrashExample)(CrashExampleAppDelegate 。米9 4

最后,如果你想从一个崩溃日志得到所有的地址,你可以使用苹果的symbolizecrashlog脚本。这一发现的。应用程序和。的dSYM文件为。的Crash.log文件,并调用ATOS得到遏制。内的每一个可能的符号感谢millenomi指出这一点的意见。

结论

有很多详细信息,在调试的时候挤出不仅仅是在你的变量的原始值。有机会获得这些信息,在调试过程中,可以跟踪Bug,只是有点快。

Objective-C编程调试技巧的更多相关文章

  1. java编程调试技巧

    1 多线程调试 开发过多线程应用的朋友应该有体会,有些时候,为了观察多个线程间变量的不同状态,以及锁的获取等,就会想到在代码里加个断点debug一下. 在IDE里断点停下来的时候,可以切换到另外的线程 ...

  2. shell编程学习笔记【原创】

    本文为本人学习笔记,如有转载请注明出处,谢谢 一.Bourne Shell 有如下四种变量: 用户自定义变量 位置变量,即命令行参数 预定义变量 环境变量 二.位置变量 $ 与键入的命令行一样,包含脚 ...

  3. Automake

    Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...

  4. [No00007F]2016-面经[下] 英文简历写作技巧

    一.简历种类 1.中式 中式简历中,常包括政治面貌,性格及身高体重等.如果中英文简历一起递交,建议中文不写政治面貌,因为如果去外企工作,背景中的政治色彩越少越好,起码没有必要让老外知道. 性格是一个主 ...

  5. iOS开发——开发技巧&LLDB详解

    开胃小菜--简单的断点调试 在xcode中打开一个app,在想要break的行号上单击,即可生成一个深色的箭头标识--断点.如下图,在viewDidLoad:中设置了断点. 运行app,等待...就可 ...

  6. KVC技巧二则

    说两个与KVC相关的技巧. 1.KVC与字典 有时候我们需要取出嵌套字典中的某个键的值.例如某个嵌套字典: NSDictionary *dict = @{@"subDict":@{ ...

  7. C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?

    C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...

  8. iOS开发核心语言Objective C —— 全部知识点总结

    本分享是面向有意向从事iOS开发的伙伴及苹果产品的发烧友,亦或是已经从事了iOS的开发人员,想进一步提升者.假设您对iOS开发有极高的兴趣,能够与我一起探讨iOS开发.一起学习,共同进步.假设您是零基 ...

  9. PHP、 Ruby、Python、Java、C++、C、Objective C——编程语言之禅

    PHP是你豆蔻年华时的心上人,她是情窦初开的你今年夏天傻乎乎追求的目标.玩一玩可以,但千万不要投入过深,因为这个“女孩”有严重的问题. Ruby是脚本家族中一个非常漂亮的孩子.第一眼看她,你的心魄就会 ...

随机推荐

  1. 初学swift笔记 枚举(七)

    import Foundation /* 枚举 语法结构 enum 类型 { case 值 } */ //定义一个枚举 写法1 enum LiuShiQun { case Name case Age ...

  2. HDU 4121 Xiangqi

    模拟吧,算是... 被这个题wa到哭,真是什么都不想说了...上代码 #include <iostream> #include <cstring> using namespac ...

  3. ModelMap和ModelAndView(转)

    转自:http://bao1073740756-126-com.iteye.com/blog/1549597 首先介绍ModelMap和ModelAndView的作用 ModelMap ModelMa ...

  4. QT:浮动的饼状统计图(自绘不规则窗口)

    昨天在玩手机游戏时,见到一个游戏的饼状投票统计图很漂亮,所以我今天也花了一个下午来实现了一个类似的程序娱乐一下,呵呵. 思路:1:将窗体设为Qt::FramelessWindowHint和Qt::WA ...

  5. poj 2393 Yogurt factory(dp+贪心)

    奶牛们建了一家酸奶厂,在N周内每周需要出货Y_i单位酸奶,第i周成本为C_i,储存费为每周S.求总体最低成本. 贪心策略是维持每周的最低单位成本,每周可能用上周剩下的,也可能生产新的.于是该周单位成本 ...

  6. react-native 自己搭建热更新服务器

    使用到的框架是 react-native-update react-native-update-cli 这个应该执行热更新的时候的终端命令. 通过这个,自己搭建一个热更新的服务器.

  7. Android解决异常apk on device '0292bea1': Unable to open sync connection!

    方式一:使用手机管家(如腾讯手机管家,只要拖动发射火箭就行了)清理一下正在运行的后台程序. 方式二:把USB数据线拔了重新链接. 方法三:找到USB调试,关掉USB调试,然后重新开启.在设置 --&g ...

  8. ORA-03113 通信通道的文件结尾(ORA-19804 ORA-16038-归档空间满的处理方法)

    1.数据库启动报错SQL> startupORACLE 例程已经启动. Total System Global Area 1887350784 bytesFixed Size 2176848 b ...

  9. DB2 runstats和reorg操作

    [db2inst1@xifenfei ~]$ db2 connect to xff      Database Connection Information    Database server    ...

  10. CentOS 6 安装 python and pip

    yum update yum list python*     //查看可安装python包 yum install python34.i686_64 wget https://bootstrap.p ...