iOS应用崩溃(三)——崩溃日志

本文详细介绍了在iOS开发中遇到内存访问错误和异常时的调试方法,包括如何在模拟器上启用堆栈跟踪,使用命令行工具获取堆栈信息,以及在实际设备上捕获和记录异常信息的方法。同时,还分享了解决内存管理问题导致的EXC_BAD_ACCESS崩溃的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、模拟器上显示堆栈信息

当我们在模拟器上调试时,可能经常遇到下面的内存访问错误:

2011-01-17 20:21:11.41 App[26067:207] * -[Testedit retain]: message sent to deallocated instance 0x12e4b

该错误是对一个已经释放的对象进行操作,定位如下:

  • (1)、设置MallocStackLogging:

    • ①、点击Xcode的Product菜单,选择Edit Scheme…选项
    • ②、选择左侧的Run…,右边点击Arguments
    • ③、在Environment Variables栏里,添加NSZombieEnabled,value为YES;再添加MallocStackLogging,value为YES;
      如下图所示:
      这里写图片描述
      以上选项只能在模拟器上有效,如果你改变了iOS的版本,需要重新设定。
      调试结束后,最好记得把环境变量NSZombieEnabled,MallocStackLogging前面的勾去掉,因为它们会使得内存不会被释放.
  • (2)、终端输入 info malloc-history 命令,即可得到堆栈信息,从而分析具体问题所在

    (gdb) info malloc-history 0x12e4b0
    
  • (3)、也可输入如下信息:

    (gdb) shell malloc_history {pid/partial-process-name} {address}
    

PS:内存使用时“EXC_BAD_ACCESS”的错误信息也是经常遇到的,这时我们只要将上面执行文件属性中的 NSZombieEnabled 选上,也能定位该问题。

二、在iPhone上输出日志

iOS开发中我们会遇到程序抛出异常退出的情况,如果是在调试的过程中,异常的信息是一目了然,但是如果是在已经发布的程序中,获取异常的信息有时候是比较困难的。

1、可以捕捉的异常(ECX_CRASH)

iOS提供了异常发生的处理API,我们在程序启动的时候可以添加这样的Handler,这样的程序发生异常的时候就可以对一部分的信息进行必要的处理,适时的反馈给开发者。NSException导致程序向自身发送了SIGABRT信号而崩溃;SIGABRT(也叫做ECX_CRASH)是一个比较好解决的Crash,以为他是一个可掌控的crash,App会在一个目的地终止,以为系统意识到app做了一些他不能支持的事情。

接口声明:

#import <Foundation/Foundation.h>
@interface NdUncaughtExceptionHandler : NSObject
+ (void)setDefaultHandler;
+ (NSUncaughtExceptionHandler*)getHandler;
@end

接口实现:

#import "NdUncaughtExceptionHandler.h"
//返回绝对路径
NSString *applicationDocumentsDirectory() {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
void UncaughtExceptionHandler(NSException *exception) {
    NSArray *arr = [exception callStackSymbols];
    NSString *reason = [exception reason];
    NSString *name = [exception name];
    NSString *url = [NSString stringWithFormat:@"=============异常崩溃报告=============\nname:\n%@\nreason:\n%@\ncallStackSymbols:\n%@",
                     name,reason,[arr componentsJoinedByString:@"\n"]];
    NSString *path = [applicationDocumentsDirectory() stringByAppendingPathComponent:@"Exception.txt"];
    [url writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
    //除了可以选择写到应用下的某个文件,通过后续处理将信息发送到服务器等
    //还可以选择调用发送邮件的的程序,发送信息到指定的邮件地址
    //或者调用某个处理程序来处理这个信息
}
@implementation NdUncaughtExceptionHandler
//返回绝对路径
-(NSString *)applicationDocumentsDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
+ (void)setDefaultHandler
{
    NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);
}
+ (NSUncaughtExceptionHandler*)getHandler
{
    return NSGetUncaughtExceptionHandler();
}
@end

调用事例:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [NdUncaughtExceptionHandler setDefaultHandler];
    NSArray *array = [NSArray arrayWithObject:@"there is only one objective in this arary,call index one, app will crash and throw an exception!"];
    NSLog(@"%@", [array objectAtIndex:1]);
    return YES;
}

崩溃信息如下:

=============异常崩溃报告=============
name:
NSRangeException
reason:
*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]
callStackSymbols:
0   CoreFoundation                      0x0000000108573c65 __exceptionPreprocess + 165
1   libobjc.A.dylib                     0x000000010820cbb7 objc_exception_throw + 45
2   CoreFoundation                      0x000000010846a17e -[__NSArrayI objectAtIndex:] + 190
3   UIColorDemo                         0x0000000107c88914 -[AppDelegate application:didFinishLaunchingWithOptions:] + 164
4   UIKit                               0x00000001090be748 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 240
5   UIKit                               0x00000001090bf357 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2540
6   UIKit                               0x00000001090c219e -[UIApplication _runWithMainScene:transitionContext:completion:] + 1349
7   UIKit                               0x00000001090c1095 -[UIApplication workspaceDidEndTransaction:] + 179
8   FrontBoardServices                  0x000000010dd095e5 __31-[FBSSerialQueue performAsync:]_block_invoke_2 + 21
9   CoreFoundation                      0x00000001084a741c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
10  CoreFoundation                      0x000000010849d165 __CFRunLoopDoBlocks + 341
11  CoreFoundation                      0x000000010849c947 __CFRunLoopRun + 887
12  CoreFoundation                      0x000000010849c366 CFRunLoopRunSpecific + 470
13  UIKit                               0x00000001090c0b02 -[UIApplication _run] + 413
14  UIKit                               0x00000001090c38c0 UIApplicationMain + 1282
15  UIColorDemo                         0x0000000107c88e4f main + 111
16  libdyld.dylib                       0x000000010afcc145 start + 1
17  ???                                 0x0000000000000001 0x0 + 1

2、内存等导致的异常(EXC_BAD_ACCESS)

引起崩溃的大多数原因如:内存访问错误(访问了不属于本进程的内存地址),重复释放错误等;EXC_BAD_ACCESS是一个比较难处理的crash了,当一个app进入一种毁坏的状态,通常是由于内存管理问题而引起的时,就会出现出现这样的crash。这种错误它抛出的是Signal,上述方法无法捕捉到。所以必须要专门做Signal处理。

代码如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoxiaobukuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值