iPhone开发技巧之调试篇(3)— 程序Crash后的调试技巧
来源:互联网 发布:猎巫运动知乎 编辑:程序博客网 时间:2024/06/02 07:52
当我们的程序突然死掉了,Xcode突然送出一段 "message sent to deallocated instance" 的错误,我们该怎样定位我们的程序bug呢?
又或者我们已经通过AdHoc发布了我们的β版程序,更甚至于我们的程序已经发布到了app store上;而当我们的程序突然在测试人员,或者是最终用户那里突然当掉,是否能收集到这样的日志信息,供我们解析bug呢?
- 下面的文章中我将逐步深入地说明这些技巧
模拟器上显示堆栈信息
当我们在模拟器上调试时,可能经常遇到下面的内存访问错误:
1
2011-01-17 20:21:11.41 App[26067:207] *** -[Testedit retain]: message sent to deallocated instance 0x12e4b0
首先,我们为了定位问题,需要Xcode帮我们显示栈信息,可以通过Scode中执行文件的属性来设置。如下图所示,选中 MallocStackLogging 选项。该选项只能在模拟器上有效,并且如果你改变了iOS的版本后也需要再次设定该选项。
这之后,你就可以在终端输入 info malloc-history 命令,如下所示;
1
(gdb) info malloc-history 0x12e4b0
之后得到如下的堆栈信息,从此分析具体的问题所在。
除此之外,也可以使用下面的命令;
1
(gdb) shell malloc_history {pid/partial-process-name} {address}
例如下图所示;
另外,内存使用时“EXC_BAD_ACCESS”的错误信息也是经常遇到的,这时我们只要将上面执行文件属性中的 NSZombieEnabled 选上,也能定位该问题。
最后,这些设置信息都是可以在运行期确认的,如下;
1
NSLog(@<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"NSZombieEnabled: %s"</span>, getenv(<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"NSZombieEnabled"</span>));
在iPhone上输出日志
如果不是在模拟器上,又或者我们的设备没有连接到PC上,那么如何调试我们的程序呢?假如我们通过AdHoc发布了程序,希望随时得到测试人员的反馈,可以利用下面的方法,将标准出力(stderr)信息记录到文件中,然后通过邮件新式发给开发者。
1. 设置一个开关,用来清空日志文件内容,并切换输出位置;
12345678
- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">BOOL</span>)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">deleteLogFile</span> { [<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span> finishLog]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">BOOL</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">success</span> = [[<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSFileManager</span> defaultManager] removeItemAtPath:[<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span> loggingPath] error:<span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">nil</span>]; [<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span> startLog]; <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">return</span> success;}
当我们调用上面的deleteLogFile后,就会清空之前的日志,并设置新的输出。
1234567891011121314151617181920
- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">finishLog</span> { fflush(stderr); dup2(dup(STDERR_FILENO), STDERR_FILENO); close(dup(STDERR_FILENO));}- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSString</span>*)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">loggingPath</span> { <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSArray</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">paths</span> = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, <span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">YES</span>); <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSString</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">documentsDirectory</span> = [paths objectAtIndex:0]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSString</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">logPath</span> = [documentsDirectory stringByAppendingPathComponent:@<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"console.log"</span>]; <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">return</span> logPath;}- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">startLog</span> { freopen([[<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span> loggingPath] cStringUsingEncoding:NSASCIIStringEncoding],<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"a+"</span>,stderr);}
2. 当日志取得之后,可以通过下面的方式发送邮件给开发者
1234567891011
- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">sendLogByMail</span> { <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">MFMailComposeViewController</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">picker</span> = [[<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">MFMailComposeViewController</span> alloc] init]; picker.mailComposeDelegate = <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span>; [picker setSubject:[<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSString</span> stringWithFormat:@<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"%@ - Log"</span>, [<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span> appName]]]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSString</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">message</span> = [<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSString</span> stringWithContentsOfFile:[<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span> loggingPath] encoding:NSUTF8StringEncoding error:<span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">nil</span>]; [picker setMessageBody:message isHTML:<span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">NO</span>]; [<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span>.navigationController presentModalViewController:picker animated:<span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">YES</span>]; [picker release];}
iPhone应用程序的CrashReporter机能
苹果在固件2.0发布的时候,其中一项特性是向iPhone开发者通过邮件发送错误报告,以便开发人员更好的了解自己的软件运行状况。不过不少开发者报告此服务有时无法获取到~/Library/Logs/CrashReporter/MobileDevice directory的错误信息。
现在苹果提供了一种更简单的方法,使iPhone开发者可以通过iTunes更容易的查看崩溃报告。具体方法使进入iTunesConnect(在进入之前确定你有iPhone开发者帐号),点击管理你应用程序,之后就可以看到用户崩溃日志了。
这里我介绍一下从设备中取出CrashLog,并解析的方法。
CrashLog的位置
程序Crash之后,将设备与PC中的iTunes连接,设备中的CrashLog文件也将一并同步到PC中。其中位置如下;
12345678
Mac:~/Library/Logs/CrashReporter/MobileDeviceWindows Vista/7:C:\Users<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">\<</span>user_name>\AppData\Roaming\Apple computer\Logs\CrashReporter/MobileDeviceWindows XP:C:\Documents and Settings<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">\<</span>user_name>\Application Data\Apple computer\Logs\CrashReporter
在这些目录下,会有具体设备的目录,其下就是许多*.crash的文件。
比如程序TestEditor在iPhone1设备上的crashLog如下:
12345678910111213141516171819202122232425262728293031323334353637
~Library/Logs/CrashReporter/MobileDevice/iPhone1/TestEditor_2010-09-23-454678_iPhone1.crashIncident Identifier: CAF9ED40-2D59-45EA-96B0-52BDA1115E9FCrashReporter Key: 30af939d26f6ecc5f0d08653b2aaf47933ad8b8eProcess: TestEditor [12506]Path: /var/mobile/Applications/60ACEDBC-600E-42AF-9252-42E32188A044/TestEditor.app/TestEditorIdentifier: TestEditorVersion: ??? (???)Code Type: ARM (Native)Parent Process: launchd [1]Date/Time: 2010-09-23 11:25:56.357 +0900OS Version: iPhone OS 3.1.3 (7E18)Report Version: 104Exception Type: EXC_BAD_ACCESS (SIGBUS)Exception Codes: KERN_PROTECTION_FAILURE at 0x00000059Crashed Thread: 0Thread 0 Crashed:0 UIKit 0x332b98d8 0x331b2000 + 10795121 UIKit 0x3321d1a8 0x331b2000 + 4386962 UIKit 0x3321d028 0x331b2000 + 4383123 UIKit 0x332b9628 0x331b2000 + 10788244 UIKit 0x33209d70 0x331b2000 + 3597925 UIKit 0x33209c08 0x331b2000 + 3594326 QuartzCore 0x324cc05c 0x324ae000 + 1229727 QuartzCore 0x324cbe64 0x324ae000 + 1224688 CoreFoundation 0x3244f4bc 0x323f8000 + 3575649 CoreFoundation 0x3244ec18 0x323f8000 + 35535210 GraphicsServices 0x342e91c0 0x342e5000 + 1683211 UIKit 0x331b5c28 0x331b2000 + 1540012 UIKit 0x331b4228 0x331b2000 + 874413 TestEditor 0x00002c3a 0x1000 + 722614 TestEditor 0x00002c04 0x1000 + 7172<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">...</span> (以下略)
虽然我们看到了出为题时的堆栈信息,但是因为没有符号信息,仍然不知道到底哪里出问题了...
.dSYM文件
编译调试相关的符号信息都被包含在编译时的 xxxx.app.dSYM 文件当中,所以我们在发布程序前将它们保存起来,调试Crash问题的时候会很有用。
首先,我们来找到该文件。
用Xcode编译的程序,在其编译目录下都会生成 [程序名].app.dSMY 文件,比如 Xcode 4 的编译目录缺省的是
12345
~Library/Developer/Xcode/DerivedData<span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;"># </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">在改目录下搜寻编译后的.dSMY文件</span>$ cd ~/Library/Developer/Xcode/DerivedData$ find . -name <span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">'*.dSYM'</span>
另外,我们也可以通过 Xcode的Preferences... -> Locations -> Locations 的Derived Data来确认该目录的位置。
- 上面例子中的程序,我们就找到了其位置是
1
~/Library/Developer/Xcode/DerivedData/TestEditor-aahmlrjpobenlsdvhjppcfqhogru/ArchiveIntermediates/TestEditor/BuildProductsPath/Release-iphoneos/TestEditor.app.dSYM
※ 大家每次像App Store发布自己程序的时候都记着保存该文件哦,要不然出现Crash的时候,就无从下手了。
解决符号问题
接下来,我们再来介绍一下使用.dSYM文件来恢复程序符号的方法。
首先,使用一个Xcode提供的叫做 symbolicatecrash 的小工具,它可以实现我们在CrashLog中添加符号信息的机能。该文件位于下面的位置,为方便起见,可以把它拷贝到系统默认路径下。
123
/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash$ sudo cp /Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash /usr/local/bin
- 使用下面的命令,可以在终端输出有符号信息的CrashLog
123
$ symbolicatecrash [CrashLog file] [dSYM file]$ symbolicatecrash TestEditor_2010-09-23-454678_iPhone1.crash TestEditor.app.dSYM
12345678910111213141516
Thread 0 Crashed:0 UIKit 0x332b98d8 -[UIWindowController transitionViewDidComplete:fromView:toView:] + 6681 UIKit 0x3321d1a8 -[UITransitionView notifyDidCompleteTransition:] + 1602 UIKit 0x3321d028 -[UITransitionView _didCompleteTransition:] + 7043 UIKit 0x332b9628 -[UITransitionView _transitionDidStop:finished:] + 444 UIKit 0x33209d70 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 2845 UIKit 0x33209c08 -[UIViewAnimationState animationDidStop:finished:] + 606 QuartzCore 0x324cc05c _ZL23run_animation_callbacksdPv + 4407 QuartzCore 0x324cbe64 _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv + 1568 CoreFoundation 0x3244f4bc CFRunLoopRunSpecific + 21929 CoreFoundation 0x3244ec18 CFRunLoopRunInMode + 4410 GraphicsServices 0x342e91c0 GSEventRunModal + 18811 UIKit 0x331b5c28 -[UIApplication _run] + 55212 UIKit 0x331b4228 UIApplicationMain + 96013 TestEditor 0x00002c3a main (main.m:14)14 TestEditor 0x00002c04 0x1000 + 7172
由此,我们可以具体定位程序中出问题的地方。
用StackTrace取得崩溃时的日志
异常处理机制
任何语言都有异常的处理机制,Objective-C也不例外。与C++/Java类似的语法,它也提供@try, @catch, @throw, @finally关键字。使用方法如下。
123456789101112
<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">@try</span> {... }<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">@catch</span> (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">CustomException</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">ce</span>) {... }<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">@catch</span> (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSException</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">ne</span>) {<span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">//</span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;"> Perform processing necessary at this level.</span>... }<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">@catch</span> (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">id</span> ue) {... }<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">@finally</span> {<span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">//</span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;"> Perform processing necessary whether an exception occurred or not.</span>... }
同时对于系统Crash而引起的程序异常退出,可以通过UncaughtExceptionHandler机制捕获;也就是说在程序中catch以外的内容,被系统自带的错误处理而捕获。我们要做的就是用自定义的函数替代该ExceptionHandler即可。
- 这里主要有两个函数
- NSGetUncaughtExceptionHandler() 得到现在系统自带处理Handler;得到它后,如果程序正常退出时用来回复系统原先设置
- NSSetUncaughtExceptionHandler() 红色设置自定义的函数
- 简单的使用例子如下所示
1234567891011121314151617181920212223242526272829303132333435
<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> <span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">MyUncaughtExceptionHandler</span>(<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSException</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">exception</span>){ printf(<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"uncaught %s\n"</span>, [[exception name] cString]); <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">~</span> <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">显示当前堆栈内容</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSArray</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">callStackArray</span> = [exception callStackReturnAddresses]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">frameCount</span> = [callStackArray count]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">backtraceFrames</span>[frameCount]; <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">for</span> (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">i</span>=0; i<frameCount; i++) { backtraceFrames[i] = (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> *)[[callStackArray objectAtIndex:i] unsignedIntegerValue]; }}<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">main</span>(){ <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">~</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSUncaughtExceptionHandler</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">ueh</span> = NSGetUncaughtExceptionHandler(); NSSetUncaughtExceptionHandler(&MyUncaughtExceptionHandler); <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">~</span>}- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">exit_processing</span>:(<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSNotification</span> *)<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">notification</span> { <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSSetUncaughtExceptionHandler</span>(<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">ueh</span>);}- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">viewDidLoad</span> { <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">这里重载程序正常退出时UIApplicationWillTerminateNotification接口</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">UIApplication</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">app</span> = [<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">UIApplication</span> sharedApplication]; [[<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSNotificationCenter</span> defaultCenter] addObserver:<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span> selector:<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">@selector</span>(exit_processing:) name:UIApplicationWillTerminateNotification object:app]}
处理signal
使用Objective-C的异常处理是不能得到signal的,如果要处理它,我们还要利用unix标准的signal机制,注册SIGABRT, SIGBUS, SIGSEGV等信号发生时的处理函数。该函数中我们可以输出栈信息,版本信息等其他一切我们所想要的。
- 例子代码如下
123456789101112131415161718192021222324252627282930313233343536373839
<span class="preprocessor" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); background-color: transparent;">#include</span> <span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;"><signal.h></span><span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> <span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">stacktrace</span>(<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">sig</span>, <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">siginfo_t</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">info</span>, <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">context</span>){ [mstr appendString:@<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"Stack:\n"</span>]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>* <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">callstack</span>[128]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">i</span>, <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">frames</span> = backtrace(callstack, 128); <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">char</span>** <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">strs</span> = backtrace_symbols(callstack, frames); <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">for</span> (i = 0; i <; frames; ++i) { [mstr appendFormat:@<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"%s\n"</span>, strs[i]]; }}<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">main</span>(<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">argc</span>, <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">char</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">argv</span>[]){ <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">struct</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">sigaction</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">mySigAction</span>; mySigAction.sa_sigaction = stacktrace; mySigAction.sa_flags = SA_SIGINFO; sigemptyset(&mySigAction.sa_mask); sigaction(SIGQUIT, &mySigAction, NULL); sigaction(SIGILL , &mySigAction, NULL); sigaction(SIGTRAP, &mySigAction, NULL); sigaction(SIGABRT, &mySigAction, NULL); sigaction(SIGEMT , &mySigAction, NULL); sigaction(SIGFPE , &mySigAction, NULL); sigaction(SIGBUS , &mySigAction, NULL); sigaction(SIGSEGV, &mySigAction, NULL); sigaction(SIGSYS , &mySigAction, NULL); sigaction(SIGPIPE, &mySigAction, NULL); sigaction(SIGALRM, &mySigAction, NULL); sigaction(SIGXCPU, &mySigAction, NULL); sigaction(SIGXFSZ, &mySigAction, NULL); <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSAutoreleasePool</span> * <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">pool</span> = [[<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSAutoreleasePool</span> alloc] init]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">retVal</span> = UIApplicationMain(argc, argv, <span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">nil</span>, <span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">nil</span>); [pool release]; <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">return</span> (retVal);}
总结
- 综上所述,我们可以看到用StackTrace取得崩溃时日志的手顺如下
- 用NSGetUncaughtExceptionHandler()取得当前系统异常处理Handler
- 用NSSetUncaughtExceptionHandler()注册自定义异常处理Handler
- 注册signal处理机制
- 注册Handler中打印堆栈,版本号等信息
- 必要的时候将其保存到dump.txt文件
- 异常程序退出
- 如果程序不是异常退出,则还原之前系统的异常处理函数句柄
- 如果下次程序启动,发现有dump.txt的异常文件,启动邮件发送报告机制
- 整体的代码框架如下
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
<span class="preprocessor" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); background-color: transparent;">#include</span> <span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;"><signal.h></span><span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> <span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">stacktrace</span>(<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">sig</span>, <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">siginfo_t</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">info</span>, <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">context</span>){ [mstr appendString:@<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"Stack:\n"</span>]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>* <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">callstack</span>[128]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">i</span>, <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">frames</span> = backtrace(callstack, 128); <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">char</span>** <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">strs</span> = backtrace_symbols(callstack, frames); <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">for</span> (i = 0; i <; frames; ++i) { [mstr appendFormat:@<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"%s\n"</span>, strs[i]]; }}<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> <span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">MyUncaughtExceptionHandler</span>(<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSException</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">exception</span>){ printf(<span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"uncaught %s\n"</span>, [[exception name] cString]); <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">~</span> <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">显示当前堆栈内容</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSArray</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">callStackArray</span> = [exception callStackReturnAddresses]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">frameCount</span> = [callStackArray count]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">backtraceFrames</span>[frameCount]; <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">for</span> (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">i</span>=0; i<frameCount; i++) { backtraceFrames[i] = (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span> *)[[callStackArray objectAtIndex:i] unsignedIntegerValue]; }}<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">main</span>(<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">argc</span>, <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">char</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">argv</span>[]){ <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">struct</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">sigaction</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">mySigAction</span>; mySigAction.sa_sigaction = stacktrace; mySigAction.sa_flags = SA_SIGINFO; sigemptyset(&mySigAction.sa_mask); sigaction(SIGQUIT, &mySigAction, NULL); sigaction(SIGILL , &mySigAction, NULL); sigaction(SIGTRAP, &mySigAction, NULL); sigaction(SIGABRT, &mySigAction, NULL); sigaction(SIGEMT , &mySigAction, NULL); sigaction(SIGFPE , &mySigAction, NULL); sigaction(SIGBUS , &mySigAction, NULL); sigaction(SIGSEGV, &mySigAction, NULL); sigaction(SIGSYS , &mySigAction, NULL); sigaction(SIGPIPE, &mySigAction, NULL); sigaction(SIGALRM, &mySigAction, NULL); sigaction(SIGXCPU, &mySigAction, NULL); sigaction(SIGXFSZ, &mySigAction, NULL); <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">~</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSUncaughtExceptionHandler</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">ueh</span> = NSGetUncaughtExceptionHandler(); NSSetUncaughtExceptionHandler(&MyUncaughtExceptionHandler); <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">~</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSAutoreleasePool</span> * <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">pool</span> = [[<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSAutoreleasePool</span> alloc] init]; <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">int</span> <span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">retVal</span> = UIApplicationMain(argc, argv, <span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">nil</span>, <span class="constant" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">nil</span>); [pool release]; <span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">return</span> (retVal);}- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">exit_processing</span>:(<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSNotification</span> *)<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">notification</span> { <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSSetUncaughtExceptionHandler</span>(<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">ueh</span>);}- (<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">void</span>)<span class="function-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); background-color: transparent;">viewDidLoad</span> { <span class="comment-delimiter" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">// </span><span class="comment" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(173, 216, 230); background-color: transparent;">这里重载程序正常退出时UIApplicationWillTerminateNotification接口</span> <span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">UIApplication</span> *<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">app</span> = [<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">UIApplication</span> sharedApplication]; [[<span class="type" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(154, 205, 50); font-weight: bold; background-color: transparent;">NSNotificationCenter</span> defaultCenter] addObserver:<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">self</span> selector:<span class="keyword" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(250, 128, 114); font-weight: bold; background-color: transparent;">@selector</span>(exit_processing:) name:UIApplicationWillTerminateNotification object:app]}
- 输入的CrashLog如下
123456789101112131415
Signal:10Stack:0 TestEditor 0x0006989d dump + 641 TestEditor 0x00069b4b signalHandler + 462 libSystem.B.dylib 0x31dcd60b _sigtramp + 263 TestEditor 0x000252b9 -[PopClientcreateUnreadMessageWithUIDL:maxMessageCount:] + 764 TestEditor 0x00025b85 -[PopClientgetUnreadIdList:] + 3485 TestEditor 0x000454dd -[Connection receiveMessages:] + 6886 TestEditor 0x00042db1 -[Connection main] + 1887 Foundation 0x305023f9 __NSThread__main__ + 8588 libSystem.B.dylib 0x31d6a5a8 _pthread_body + 28AppVer:TestEditor 1.2.0System:iPhone OSOS Ver:3.0Model:iPhoneDate:09/06/08 21:25:59JST
其中从_sigtramp函数下面开始进入我们的程序,即地址0x000252b9开始。其所对应的具体文件名和行号我们能知道吗?
利用之前介绍的dSYM文件和gdb,我们可以得到这些信息。
1234567
<span class="builtin" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(117, 128, 213); background-color: transparent;">cd</span> $<span class="variable-name" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(127, 255, 212); font-weight: bold; background-color: transparent;">PROJ_PATH</span>$/build/Release-iphoneos/TestEditor.app.dSYM/<span class="builtin" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(117, 128, 213); background-color: transparent;">cd</span> Contents/Resources/DWARFgdb TestEditorgdb>info line *0x000252b9Line 333 of <span class="string" style="border: 0px; outline: 0px; vertical-align: baseline; margin: 0px; padding: 0px; color: rgb(255, 160, 122); background-color: transparent;">"~/IbisMail/Classes/Models/PopClient.m"</span>;starts at address 0x2a386 <-[PopClient retrieve:]+86> andends at 0x2a390 <-[PopClient retrieve:]+96>
- iPhone开发技巧之调试篇(3)— 程序Crash后的调试技巧
- iPhone开发技巧之调试篇(3)— 程序Crash后的调试技巧
- iPhone开发技巧之调试篇(3)— 程序Crash后的调试技巧
- iPhone开发技巧之调试篇(3)— 程序Crash后的调试技巧
- iPhone开发技巧之调试篇— 程序Crash后的调试技巧
- iPhone开发技巧之调试篇 — 程序Crash后的调试技巧
- Phone开发技巧之调试篇(3)— 程序Crash后的调试技巧
- iPhone开发技巧之调试 — 程序Crash后的调试技巧
- 程序Crash后的调试技巧
- 程序Crash后的调试技巧
- iPhone开发技巧之调试篇(1)--- 调试由URL scheme启动的进程
- iPhone开发技巧之调试篇— 保存日志
- iPhone开发技巧之调试篇(2)— 保存日志
- Xcode调试技巧之二 crash之后的定位问题
- Xcode调试技巧之二 crash之后的定位问题
- Xcode调试技巧之二 crash之后的定位问题
- iOS Crash(崩溃)调试技巧
- iphone调试技巧
- 【android动态布局】之【ListView动态加载数据模板(使用xml布局)】
- 多线程之线程初始
- Neural Networks for Machine Learning by Geoffrey Hinton (4)
- Android ActionBar总结一
- 浅谈Spring事务隔离级别
- iPhone开发技巧之调试篇(3)— 程序Crash后的调试技巧
- 理解 Linux 的硬链接与软链接
- 匿名项目连载(五)--->发布说说
- 加载大图,解决oom问题
- 男人和小姨子看到一辆豪华的进口轿车,小姨子竟然说……
- tomcat的work目录的作用
- SQLite组合主键设置外键以及出现外键匹配出错System.Data.SQLite.SQLiteException (0x80004005) SQL logic error or missing d
- Javascript实现幻灯片效果
- java系统学习(四) --------java字符串的处理