Obj-c Xcode静态分析在指针赋值时产生“空指针的解引用”

时间:2013-03-29 13:57:49

标签: objective-c xcode static-analysis objective-c-runtime

我正在尝试实现一个棘手的事情:我的所有模型类都有自己的属性的NSCoding实现。这让我可以为我的类添加和删除属性,而不用担心丢失的东西没有被编码/解码。 (实际上,它也有其他用途,但这是主要的想法)。

当使用initWithCoder从存档初始化我的对象时,由于Obj-C运行时,我浏览了我的属性列表,并尝试直接将ivars分配给值。我不想因为各种各样的原因而通过setter,因此setValue:forKey:被禁止。

有趣的问题,不是吗?我必须说我对C指针的微妙之处并不完全自信......

以下是代码:

unsigned int outCount;
objc_property_t *properties = class_copyPropertyList(class, &outCount);

for (unsigned int index = 0; index < outCount; index++) {
    objc_property_t property = properties[index];
    NSString *propertyNameString = [NSString stringWithUTF8String:property_getName(property)];

    id value = [coder decodeObjectForKey:propertyNameString];
    if (value == nil) {
        continue;
    }

    const char *attributes = property_getAttributes(property);
    NSString *typeAttribute = [[NSString stringWithUTF8String:attributes] substringWithRange:NSMakeRange(1, 1)];
    const char *ivarName = [[@"_" stringByAppendingString:propertyNameString] UTF8String];

    if ([typeAttribute isEqualToString:@"@"]) {
        Ivar ivar = class_getInstanceVariable([self class], ivarName);
        object_setIvar(self, ivar, value);
    }
    else if ([typeAttribute isEqualToString:@"d"]) {
        double *doublePointer = getIvarPointer(self, ivarName);
        *doublePointer = [value doubleValue];
    }
    else if ([typeAttribute isEqualToString:@"i"]) {
        int *intPointer = getIvarPointer(self, ivarName);
        *intPointer = [value intValue];
    }
    else if ([typeAttribute isEqualToString:@"c"]) {
        char *charPointer = getIvarPointer(self, ivarName);
        *charPointer = [value boolValue];
    }
    else if ([typeAttribute isEqualToString:@"Q"]) {
        NSUInteger *uintegerPointer = getIvarPointer(self, ivarName);
        *uintegerPointer = [value unsignedIntegerValue];
    }
}

free(properties);

'getIvar'函数看起来像这样(是的,我在对象类上使用class_getInstanceVariable,因为ARC不允许使用object_getInstanceVariable):

static void* getIvarPointer(id object, char const *name)
{
    Ivar ivar = class_getInstanceVariable(object_getClass(object), name);
    if (!ivar) return 0;
    return (unsigned char *)(__bridge void *)object + ivar_getOffset(ivar);
}

当运行Xcode的静态分析器时,我收到一条警告,说“取消引用空指针(从变量'doublePointer'加载)”。有趣的是,int和NSUInteger出现了类似的消息,但现在似乎已经消失了......它从未出现过'char'。

非常感谢任何想法,建议或富有洞察力的批评。

我必须说,代码确实有效。我确实在我的对象类中自动解码double和int。但我想明白为什么静态分析仪会告诉我这样的事情。

1 个答案:

答案 0 :(得分:0)

由于你的getIvarPointer()函数可以合理地返回0,你必须在我认为的每个* ptr效果中处理这种可能性。 例如:

if ([typeAttribute isEqualToString:@"d"]) {
    double *doublePointer = getIvarPointer(self, ivarName);
    if (doublePointer) {
        *doublePointer = [value doubleValue];
    } else {
        // Handle this as you can ;)
    }
}