2012-02-15 14 views
4

私はNSInvocationを使用してメソッドの戻り値を取得していますが、残念ながら私はリークがあるようですが、私がNSInvocationから戻った後、私は割り当てています。NSOperationQueueを使用すると、返された後にmalloc'd void *が返された後に返されます

次の実装では、次の実行ループで実行されるブロックで解放しようとしましたが、割り当てられていない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 はジョシュの-[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; 
+0

Datリリースtho。 – immibis

答えて

2

のおかげであなたはmalloc()からちょうどあなたができるように、NSMutableDataからvoid *を取得し、基本的に変えることができ、次のように動作するようにそれを手に入れましたこれをインスタンス変数に代入して、割り当ての有効期間をインスタンスの存続期間に関連付けます。私は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配列が割り当て解除されます。それ以外の場合は、dealloc[allocations release]と入力してください。

free()は、malloc()から得られなかったポインタでは動作しません。ポインタがブロック内で使用されるとき、私はそれがコピーされることを確信しているので、別のポインタで終わる - まだ同じメモリを指しているが、free()はそれが所有しているとは思わない。したがって、割り当てられていないというエラーが表示されます。

+0

ありがとう、私はあなたの実装にかなり従っていませんが、NSMutableData mutableBytesのトリックは、まさに私が何をしているかのようです。 –

+0

うれしいです!私はあなたが何かを明確にしようとすることができます。 –

+0

申し訳ありませんが、私はそれをより明確にすべきでした。私は同じ方法で実装しているわけではないので、あなたの実装に「追従している」わけではありません。あなたの実装についてのあなたの答えは非常に明確でした。 –

関連する問題