美文网首页
iOS异常奔溃捕捉

iOS异常奔溃捕捉

作者: lukyy | 来源:发表于2025-11-26 10:34 被阅读0次

真机测试的,怎么查看保存的日志

通过 Xcode 导出 App 沙盒 → 找到 Documents/CrashLogs**
这是真机调试查看本地文件最常用、最稳定的方式。
步骤:
1 连接你的 iPhone
2 打开 Xcode
3 点击菜单:Window → Devices and Simulators
4 选中你的 iPhone
5 在右侧选中你安装的 App
6 点击下面的按钮:Download Container…
7 打开下载到本地的 .xcappdata 文件
8 进入路径:

📌 奔溃完整汇总表

崩溃类型 最短复现示例
SIGABRT 数组越界 / KVC key 不存在 / NSAssert
SIGSEGV:访问非法内存地址 NULL 指针、野指针、C 数组越界
SIGBUS 非对齐指针访问 / mmap 文件被截断
EXC_BAD_ACCESS 访问已释放对象(use-after-free)
EXC_CRASH (SIGKILL) 主线程死循环(Watchdog)、OOM 内存爆掉
NSInternalInconsistencyException UIKit 非主线程、TableView 状态不一致、AutoLayout 冲突


⚠️ 注意:以下例子都是故意制造崩溃,用于学习和验证,请只在测试工程中使用。

✅ 1)制造 SIGABRT

(未捕获的 Objective-C 异常 / abort())

例 1:数组越界(最常见 SIGABRT)
- (void)causeSIGABRT {
    NSArray *arr = @[];
    NSLog(@"%@", arr[1]);   // ❌ 越界 → 抛出 NSRangeException → SIGABRT
}
例 2:KVC 找不到 key
- (void)causeSIGABRT_KVC {
    NSObject *obj = [NSObject new];
    [obj setValue:@"123" forKey:@"unknownKey"]; // ❌ NSUnknownKeyException → SIGABRT
}
例 3:NSAssert 失败
- (void)causeSIGABRT_Assert {
    NSAssert(NO, @"Force abort");  // ❌ 断言失败 → abort() → SIGABRT
}

✅ 2)制造 SIGSEGV

(访问非法内存地址 / segmentation fault)

例 1:访问 NULL 指针
- (void)causeSIGSEGV_NULL {
    int *p = NULL;
    *p = 10;   // ❌ 对 0x0 写 → SIGSEGV
}
例 2:野指针(访问已释放内存)
- (void)causeSIGSEGV_WildPointer {
    NSObject *obj = [NSObject new];
    __unsafe_unretained NSObject *ptr = obj;
    obj = nil;     // ARC 释放对象
    NSLog(@"%@", ptr.description);  // ❌ 访问已释放对象 → SIGSEGV
}
例 3:数组越界 C 指针
- (void)causeSIGSEGV_CArray {
    int arr[2] = {1,2};
    int x = arr[5];  // ❌ 越界读取 → SIGSEGV
    NSLog(@"%d", x);
}

✅ 3)制造 SIGBUS

(总线错误 / 非对齐访问 / mmap)

例 1:对齐错误(iOS 上可复现)
- (void)causeSIGBUS_Unaligned {
    uint32_t value = 0x12345678;
    char *p = (char *)&value;
    uint32_t *badPtr = (uint32_t *)(p + 1); // ❌ 非4字节对齐
    uint32_t x = *badPtr;                   // → SIGBUS
    NSLog(@"%u", x);
}
例 2:访问被截断的 mmap 文件
#import <sys/mman.h>

- (void)causeSIGBUS_mmap {
    NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"bus.txt"];
    NSData *d = [@"123456" dataUsingEncoding:NSUTF8StringEncoding];
    [d writeToFile:path atomically:YES];

    int fd = open([path UTF8String], O_RDONLY);
    char *addr = mmap(NULL, 1024, PROT_READ, MAP_SHARED, fd, 0);

    truncate([path UTF8String], 1);  // ❌ 截断文件
    char x = addr[10];               // 访问已被截断的映射 → SIGBUS
    NSLog(@"%c", x);
}

✅ 4)制造 EXC_BAD_ACCESS

(访问已释放对象 / use-after-free)

例 1:使用已经释放的对象(经典 BAD_ACCESS)
- (void)causeBADACCESS {
    __unsafe_unretained NSObject *obj;
    @autoreleasepool {
        NSObject *tmp = [NSObject new];
        obj = tmp;      // unsafe_unretained 指向 tmp
    }                    // tmp 被释放
    NSLog(@"%@", obj);   // ❌ 访问已释放 → EXC_BAD_ACCESS
}
例 2:Block 中捕获已释放对象
- (void)causeBADACCESS_Block {
    __unsafe_unretained NSObject *obj = [NSObject new];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@", obj);  // ❌ obj 被释放 → EXC_BAD_ACCESS
    });
}

✅ 5)制造 EXC_CRASH (SIGKILL)

(进程被系统强制杀死:Watchdog、memory、越权限)
⚠️ SIGKILL 无法在同一进程捕获,CrashHandler 拿不到必须用系统日志。

例 1:主线程卡死(Watchdog Kill)
- (void)causeSIGKILL_Watchdog {
    // ⚠️ 请在真机运行,模拟器不会触发 Watchdog
    while (1) { }  // ❌ 主线程死循环 → Watchdog → SIGKILL(EXC_CRASH)
}
例 2:疯狂占用内存(Out of Memory → SIGKILL)
- (void)causeSIGKILL_OOM {
    NSMutableArray *arr = [NSMutableArray array];
    while (1) {
        [arr addObject:[NSData dataWithLength:50 * 1024 * 1024]];  
        // 持续占内存 → 内存压力 → OOM → SIGKILL
    }
}

✅ 6)制造 NSInternalInconsistencyException

(UIKit / Foundation 的内部状态不一致)

例 1:UI 不在主线程修改
- (void)causeInternalInconsistency_UIThread {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        UILabel *lab = [UILabel new];
        lab.text = @"Hello";  // ❌ UIKit 非主线程操作 → NSInternalInconsistencyException
    });
}
例 2:UITableView 数据源不一致
- (void)causeInternalInconsistency_Table {
    UITableView *table = [[UITableView alloc] init];
    [table beginUpdates];
    // 删除 1 行,但数据源没有同步 → 内部状态不一致
    [table deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]]
                 withRowAnimation:UITableViewRowAnimationAutomatic];
    [table endUpdates];  // ❌ NSInternalInconsistencyException
}
例 3:AutoLayout 冲突(也可能出现)
- (void)causeInternalInconsistency_Constraint {
    UIView *v1 = [UIView new];
    UIView *v2 = [UIView new];
    [v1 addSubview:v2];

    NSLayoutConstraint *c1 = [v2.widthAnchor constraintEqualToConstant:100];
    NSLayoutConstraint *c2 = [v2.widthAnchor constraintEqualToConstant:50];
    c1.active = YES;
    c2.active = YES;  // ❌ 相互矛盾 → AutoLayout 异常 → 内部不一致
}

相关文章

  • iOS奔溃日志分析

    iOS奔溃日志分析 前言(扯淡) iOS奔溃日志能够比较有效的分析奔溃的原因,方便我们debug我们的项目。当然现...

  • DYLD, Library not loaded: /usr/l

    奔溃日志 奔溃表现:iOS12.1 及以下启动奔溃奔溃日志: 解决方法:关闭bitcode,重新打包上传appst...

  • iOS-千奇百怪的奔溃

    App 上线后,我们最怕的应该就是异常奔溃了。常见的奔溃类型分两种:信号可捕获奔溃、信号不可捕获奔溃,前者比较典型...

  • iOS奔溃信息类型捕捉与分析

    iOS 异常奔溃类型分类 1.数组越界导致的崩溃 2.数据集合类型,如字典、数组中插入元素时,插入空指针nil 3...

  • iOS13 textfield的placeholder字体颜色崩

    由于iOS13禁止了textfield通过KVC获取私有属性,出现奔溃问题 奔溃报错Access to UITex...

  • iOS崩溃类型

    奔溃类型:·Mach kernel exceptions //内核异常· Fatal signals //信号 ...

  • 2018-07-26 异常android.util.Andro

    跳转界面奔溃了,异常 android.util.AndroidRuntimeException: Calling...

  • iOS Crash(崩溃)类型

    废话不多说,直接看iOS APP奔溃的几种类型 1.Mach异常 Mach 是一个 XNU 的微内核核心,Mach...

  • iOS开发-Crash捕捉

    1、手动捕捉crash 即使有了bugly,也需要知道奔溃是如何捕捉的。注意:自定义NSSetUncaughtEx...

  • Android应用异常奔溃捕获

    应用发布上线后,难免会有bug导致应用奔溃异常退出,FC等现象,及时获取错误信息,定位bug位置,成了首要问题。

网友评论

      本文标题:iOS异常奔溃捕捉

      本文链接:https://www.haomeiwen.com/subject/ipwrqstx.html