为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. 关于Asp.net超时,延长读取sql server数据库的超时时间!(已解决)

    昨天,接到客户反映说应用报“超时时间已到.在操作完成之前超时时间已过或服务器未响应”问题.从网上了一些资料,发现这个问题还是很普遍的.主要有以下两种解决方法: 第一种方法:在web.config中加上 ...

  2. fragment低版本

    http://bbs.csdn.net/topics/390271980 Fragment框架开发东西确实很方便,但是恼人的是从4.0才开始支持.以前的版本必须用兼容模式开发,本人在网上找了大量资料, ...

  3. Linux下chkconfig命令详解(转)

    Linux下chkconfig命令详解 chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. ...

  4. poj1458 dp入门

    Common Subsequence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 37551   Accepted: 15 ...

  5. Connect the Cities(prime)

    Connect the Cities Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) ...

  6. WordPress中文汉字username不能注冊怎么办?

    WordPress注冊用户是不支持中文的.可是近期在项目中须要用到中文注冊. 后来想到了简单的处理办法: 打开 wp-includes/formatting.php.找到 function sanit ...

  7. Swift String 一些常用方法

    //字符串 //1 判断字符串是否为空 var test1Str="" var test1Str2:String = String(); println("test1St ...

  8. Android studio SweetAlert for Android

    找到个开源项目.github:https://github.com/pedant/sweet-alert-dialog 效果图:https://raw.githubusercontent.com/pe ...

  9. CSSREM插件

    CSSREM 一个CSS的px值转rem值的Sublime Text 3自动完成插件. 插件效果如下: 安装 下载本项目,比如:git clone https://github.com/flashli ...

  10. android系统将普通应用升级为系统应用

    作为一名程序员,有的时候并不是使用软件,而是去改造软件,不仅仅只是会编程而已,还要满足客户的需求.这样,才能开发出符合客户需求的应用,在关于到涉及到android底层的应用的时候,手机就需要root了 ...