美文网首页
iOS 可变长参数 va_arg exc_bad_access

iOS 可变长参数 va_arg exc_bad_access

作者: Mr_Zander | 来源:发表于2020-07-08 16:00 被阅读0次

    废话少说,直接上代码。

    函数实现
    - (void)doSomethingWithItems:(NSObject *)obj1, ... {
        va_list args;
        va_start(args, obj1);
        NSObject *item;
        while (item = va_arg(args, NSObject *)) {
            // do something
        }
    }
    
    // 函数调用
    - (void)method {
        NSObject *param1 = [NSObject alloc] init];
        NSObject *param2 = [NSObject alloc] init];
        NSObject *param3 = [NSObject alloc] init];
        [xxx doSomethingWithItems:param1, param2, param3];
    }
    

    执行,exc_bad_access崩溃。

    把调用改成:

    - (void)method {
        NSObject *param1 = [NSObject alloc] init];
        NSObject *param2 = [NSObject alloc] init];
        NSObject *param3 = [NSObject alloc] init];
        [xxx doSomethingWithItems:param1, param2, param3, nil];
    }
    

    不崩溃。
    可变长参数需要明确指定结尾,不然会野指针。
    如果在每次调用的地方都手动增加nil很蠢。

    高级方法是在函数定义的地方增加哨兵宏NS_REQUIRES_NIL_TERMINATION

    - (void)doSomethingWithItems:(NSObject *)obj1, ... NS_REQUIRES_NIL_TERMINATION
    

    此时调用该方法会自动补全nil

    NSArray的初始化方法中有这种用法
    + (instancetype)arrayWithObjects:(ObjectType)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
    但是在NSString的可变长初始化方法中确没有哨兵宏+ (instancetype)stringWithFormat:(NSString *)format, ...

    那是因为在format参数中已经明确指定了参数的个数。如果我们不想使用哨兵宏也可以在方法的第一个参数中指定个数。

    欢迎关注微信公众号查看更多高质量文章:爱编程的大头

    相关文章

      网友评论

          本文标题:iOS 可变长参数 va_arg exc_bad_access

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