4

NSInvocation用来获取一些方法返回,不幸的是我似乎有泄漏,但void*在我从NSInvocation.

在以下实现中,我尝试使用在下一个运行循环中执行的块来释放它,但由于returnBuffer未分配而导致崩溃。

为什么我不能returnBuffer在块中释放,如果它没有被分配,为什么它会通过returnBuffer!=NULL

这是一种与IMPswizzling 有关的特殊方法,所以我不知道方法返回类型。把它放进去NSData或什么都行不通。

NSUInteger length = [[invocation methodSignature] methodReturnLength];
if(length!=0){
    void* returnBuffer = (void *)malloc(length);
    [invocation getReturnValue:&returnBuffer];
    if(returnBuffer!=NULL){
        void(^delayedFree)(void) = ^{ free(returnBuffer); };
        [[NSOperationQueue mainQueue] addOperationWithBlock:delayedFree];
    }
    return returnBuffer;
}
return nil;

答案 由于乔希的-[NSMutableData mutableBytes]技巧

 NSUInteger length = [[invocation methodSignature] methodReturnLength];
if(length!=0){
    NSMutableData * dat = [[NSMutableData alloc] initWithLength:length];
    void* returnBuffer =  [dat mutableBytes];
    [invocation getReturnValue:&returnBuffer];
    void(^delayedFree)(void) = ^{ [dat release]; };
    [[NSOperationQueue mainQueue] addOperationWithBlock:delayedFree];
    return returnBuffer;
}
return nil;
4

1 回答 1

2

你可以得到一个void *from NSMutableData,就像你可以 from 一样malloc(),本质上把它变成一个实例变量,这样分配的生命周期就与实例的生命周期相关联。我从Mike Ash那里得到了这个技巧。我最近一直在NSInvocation自嘲。这是在一个类别中NSInvocation(当然,您应该为该方法使用自己的前缀):

static char allocations_key;
- (void *) Wool_allocate: (size_t)size {
    NSMutableArray * allocations = objc_getAssociatedObject(self, 
                                                            &allocations_key);
    if( !allocations ){
        allocations = [NSMutableArray array];
        objc_setAssociatedObject(self, &allocations_key, 
                                 allocations, OBJC_ASSOCIATION_RETAIN);
    }

    NSMutableData * dat = [NSMutableData dataWithLength: size];
    [allocations addObject:dat];

    return [dat mutableBytes];
}

我不确定您发布的代码在哪里;如果您在自己的自定义类中,则不需要处理关联的对象位——只需创建allocations一个 ivar。

将此绑定到您的代码中:

NSUInteger length = [[invocation methodSignature] methodReturnLength];
if(length!=0){
    void* returnBuffer = [self Wool_allocate:length];
    [invocation getReturnValue:&returnBuffer];
    return returnBuffer;
}
return nil;

如果您使用关联对象路由,则allocations当此实例存在时,数组将被释放。否则,只需放入[allocations release]您的dealloc.

此外,按照提出的方式回答您的问题,而不仅仅是解决问题:free()不会对您没有从malloc(). 当指针在块中被使用时,我很确定它会被复制,所以你最终会得到另一个指针——仍然指向同一个内存,但它free()并不认为它拥有。因此,您会收到有关未分配它的错误。

于 2012-02-15T05:34:26.243 回答