返回后使用NSOperationQueue延迟释放malloc'd void *

时间:2012-02-15 05:21:13

标签: objective-c c malloc objective-c-blocks nsinvocation

我正在使用NSInvocation来获取一些方法返回,不幸的是我似乎有泄漏,但是在我之后无法弄清楚如何释放我分配的void*我从NSInvocation返回了它。

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

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

这是一种与IMP调配有关的特殊方法,因此我不知道方法返回类型。将其放入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;

ANSWER 的 由于Josh的-[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;

1 个答案:

答案 0 :(得分:2)

您可以void *NSMutableData获得malloc(),就像您可以从NSInvocation获得NSInvocation,并且基本上将其转换为实例变量,以便分配的生命周期与实例的生命周期。我从Mike Ash得到了这个技巧。我最近一直在做一些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上的一个类别(当然,你应该使用自己的方法前缀):

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

我不确定您发布的代码位于何处;如果你在自己的自定义类中,则不需要处理关联的对象位 - 只需将allocations设为ivar。

将此与您的代码联系起来:

[allocations release]

如果使用关联的对象路由,则在此实例时将释放dealloc数组。否则,只需将free()放入malloc()

此外,要回答您提出的问题,而不仅仅是解决问题:free()不会对您未从{{1}}获得的任何指针进行操作。当指针在Block中使用时,我很确定它会被复制,所以你最终会得到另一个指针 - 仍然指向同一个内存,但{{1}}没有不认为它拥有。因此,您会收到有关未分配它的错误。