【问题标题】:Obj-c Xcode static analysis produces a "Dereference of null pointer" on pointer assignmentObj-c Xcode 静态分析在指针分配上产生“空指针的取消引用”
【发布时间】:2013-03-20 05:51:09
【问题描述】:

我正在尝试实现一件棘手的事情:我所有的模型类都有其属性的自动 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 的静态分析器时,我收到一条警告“Dereference of null pointer (loaded from variable 'doublePointer')”。有趣的是,int 和 NSUInteger 出现了类似的消息,但现在似乎已经消失了……它从未出现在 'char' 中。

非常感谢任何想法、建议或有见地的批评。

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

【问题讨论】:

  • 旁注:类型字符串的构造超级低效。你为什么不直接switch (attributes[0])
  • 感谢您的提示。没有解释,只是习惯使用 Obj-C 字符串而不是 C 字符串。
  • 不客气。我是在做 iOS 开发之前单独学习 C 的人之一,所以这些往往会引起我的注意:)
  • 是不是太明显了,以至于我反其道而行之? ;-)
  • 是的,很显眼:)

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


【解决方案1】:

由于您的 getIvarPointer() 函数可以清楚地返回 0,因此您必须在我认为的每个 *ptr 做作中处理这种可能性。 例如:

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

【讨论】:

  • 确实很好,我会纠正的。但它仍然没有解释为什么它没有在 *charPointer 上弹出,对吧?
  • Clang 通常尽量不重复错误;如果一个失败会导致一连串的问题,它会尝试只显示第一个。有时它搞砸了。这可能是一个错误,或者,如果它足够智能,可以进行跨功能边界流分析,那么它可能会在假设您修复该功能的情况下被压制。 IE。它很容易成为一个错误,如果你有动力,你可以探索它发生的情况并提交它!
猜你喜欢
  • 1970-01-01
  • 2021-09-05
  • 2015-03-20
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
相关资源
最近更新 更多