开发者

Error while getting properties types of large class in objective-C

开发者 https://www.devze.com 2023-04-08 05:53 出处:网络
In Objective-c, I am trying to get properties of some Objec开发者_如何学Pythont that contains about 14 property using the following code:

In Objective-c, I am trying to get properties of some Objec开发者_如何学Pythont that contains about 14 property using the following code:

-(NSDictionary*) getPropertiesOfClass:(Class) clazz
{
    NSMutableDictionary* dict = [NSMutableDictionary dictionary];
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(clazz, &outCount);
    for(i = 0; i < outCount; i++)
    {
        objc_property_t _property = properties[i];
        const char *propName = property_getName(_property);
        if(propName) 
        {
            const char *propType = getPropertyType(_property);
            NSString *propertyName = [NSString stringWithCString:propName encoding:NSUTF8StringEncoding];
            NSString *propertyType = [NSString stringWithCString:propType encoding:NSUTF8StringEncoding];
            [dict setValue:propertyType forKey:propertyName];
        }
    }
    free(properties);
    return dict;
}

static const char *getPropertyType(objc_property_t property) 
{
    const char *attributes = property_getAttributes(property);
    char buffer[1 + strlen(attributes)];
    strcpy(buffer, attributes);
    char *state = buffer, *attribute;
    while ((attribute = strsep(&state, ",")) != NULL) 
    {
        if (attribute[0] == 'T') 
        {
            return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
        }
    }
    return "@";
}

But I got an exception (see below) However, When I try to use the same code to get the properties list of small objects (objects with 3 or 4 properties), the code works without any exceptions and get accurate results.

So, How to handle this error!! Thanks.

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:]: absurd length: 4294967294, maximum size: 2147483648 bytes'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x0101e5a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x01172313 objc_exception_throw + 44
    2   CoreFoundation                      0x00fd6ef8 +[NSException raise:format:arguments:] + 136
    3   CoreFoundation                      0x00fd6e6a +[NSException raise:format:] + 58
    4   Foundation                          0x00800b6b -[NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:] + 135
    5   Foundation                          0x00811801 -[NSData(NSData) initWithBytes:length:] + 72
    6   solit                               0x00033449 -[ObjectMapper(private) getPropertiesOfClass:] + 489
    7   solit                               0x00031fa5 -[ObjectMapper objectFromDictionary:object:] + 197
    8   solit                               0x000327b3 -[ObjectMapper objectFromDictionary:object:] + 2259
    9   solit                               0x00033913 -[NSDictionary(ObjectMapper) toObject:withTypes:] + 243
    10  solit                               0x00031474 -[JsonWSCaller call:types:error:] + 196
    11  solit                               0x0003f4c2 +[SummaryWSCaller getFastData:] + 354
    12  solit                               0x00006fd9 -[PartSearchResultView tableView:didSelectRowAtIndexPath:] + 233
    13  UIKit                               0x00110b68 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140
    14  UIKit                               0x00106b05 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 219
    15  Foundation                          0x0082079e __NSFireDelayedPerform + 441
    16  CoreFoundation                      0x00fff8c3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
    17  CoreFoundation                      0x01000e74 __CFRunLoopDoTimer + 1220
    18  CoreFoundation                      0x00f5d2c9 __CFRunLoopRun + 1817
    19  CoreFoundation                      0x00f5c840 CFRunLoopRunSpecific + 208
    20  CoreFoundation                      0x00f5c761 CFRunLoopRunInMode + 97
    21  GraphicsServices                    0x012561c4 GSEventRunModal + 217
    22  GraphicsServices                    0x01256289 GSEventRun + 115
    23  UIKit                               0x000a7c93 UIApplicationMain + 1160
    24  solit                               0x00002289 main + 121
    25  solit                               0x00002205 start + 53
)


That's not related to the size of the class nor the number of properties.

This is probably because you have a problem in your memory mgmt. When there are not too much properties, the memory used to retrieve the property name and types in the const char* variables are still there, but when you start having too much properties to loop thru, these memory zones are erased by new values, hence the crash.

This is probably related to the fact that strsep is not reentrant too, so looping and using it multiple times uses the same internal char buffer each time.

You should make your getPropertyType method directly return the NSData object instead of the const char* bytes, and use NSString's initWithData:encoding: method to build the string from it (or move this initWithData:encoding: call to getPropertyType directly and make this return an NSString object directly. This way you will avoid managing pointers to memory zones that are to be autoreleased soon.


But your problem is probably that you forgot to check the validity of the attribute buffer and especially its length before trying to access the bytes in this buffer !

Especially you are using [NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] without checking that attribute is at least 4 characters long!

That's why the call to dataWithBytes:length: (that internally calls initWithBytes:length:copy:freeWhenDone:bytesAreVM:) crash with a NSInvalidArgumentException, telling that you pass it an absurd length of 4294967294 (which is -2 if interpreted as signed integer)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号