【问题标题】:memory leak when using callback使用回调时内存泄漏
【发布时间】:2011-09-14 15:25:28
【问题描述】:

在处理目标 c 中的回调和异步代码时,我遇到了内存管理问题。 我似乎无法找到释放设置回调的实例的方法。

例如:

MyClass *myArchive = [[MyClass alloc] init]  ;
[myArchive callBack:^(RKObjectLoader* objectLoader, id object ) {

    NSLog(@"success");

} fail:^(RKObjectLoader* objectLoader, NSError* error) {

    NSLog(@"failed");


}];

[myArchive searchArchive:words:paging];

问题是我不知道何时或如何释放实例 *myArchive。使用 xcode 中的 Instruments 来分析我的代码,我总是在这里遇到泄漏。函数 searchArchive 使用 restkit 向服务器执行异步请求。我不会从回调中引用该实例,因为我听说这会导致保留周期,并且我已经阅读了一些关于使用 __block 和其他 c 方法来避免保留周期的内容,这一切都很好,但现在没有实际代码发生在回调我如何释放 *myArchive 实例。谁能在objective-c 中解释我应该如何处理这个问题?

编辑:

这是我在 myclass 中设置回调的地方

// Sets internal backs on this object which basically wrap the delegate 
//
- (void)callBack: (void (^)(RKObjectLoader* objectLoader, id object))success 
            fail: (void (^)(RKObjectLoader* objectLoader, NSError* error))fail {
    //sanity check
    NSAssert(_currentDelegate != self, @"Delegate is another object.  Can not set callback");

    // store our callback blocks in the instance

    _success = [success copy]  ;
    _fail = [fail copy]  ;
}

然后在dealloc中释放_success和_fail

在@interface内

@interface myClass : NSObject<RKObjectLoaderDelegate> { 
    // holds the block callback for "success"
    void (^_success)(RKObjectLoader* objectLoader, id object);
    // holds the block callback for "fail"
    void (^_fail)(RKObjectLoader* objectLoader, NSError* error);
}

我希望这能让我更深入地了解我做错了什么。

编辑 2:

好的,我现在开始看到错误:

-(void)retrieveGallery{    

    //create call back for async and deal with the result
    [_galleryItems callBack:^(RKObjectLoader* objectLoader, NSArray *objects) {

        //success happy days. do a bunch of code here that does not cause leaks

    } fail:^(RKObjectLoader* objectLoader, NSError* error) {
        //retry the attempt to retrieve gallery data from the server 
        _retryCount++;
        if (_retryCount < _maxRetryCount) {
            [self retrieveGallery];
        }


    }];

    //read the collection of gallery items from server   
    [_galleryItems readGallery];

 }

唯一实际的内存泄漏是当回调因任何原因捕获失败,然后从回调中调用 [self retrieveGallery] 函数再次尝试。这就是导致泄漏的原因,所以我猜这是一个很大的禁忌。我应该如何再次尝试该功能(在这种情况下为retrieveGallery)。

【问题讨论】:

    标签: objective-c memory-leaks restkit


    【解决方案1】:

    内存管理并没有什么不同,因为您使用的是异步回调。 myArchive 应该是您在其中执行此操作的任何类的属性。您希望它一直存在直到任务完成,对吧?

    @property (retain) MyClass *myArchive;
    

    那么..

    myArchive = [[MyClass alloc] init];
    
    void (^on_success_callback)(void) = ^(void){
        NSLog(@"success");
        self.myArchive = nil;
    };
    

    您需要确保正确管理回调,即从堆栈中复制它们并在完成后释放它们。

    如果您的代码中有保留和释放,您可能没有正确使用访问器方法。

    【讨论】:

    • 这项工作的结果是偶然的,可能会导致提前释放myArchive。只需更改 @property 的原子性即可导致 myArchive 解除分配,同时在后台线程上进行测试时仍调用回调。
    • 是的,经过进一步测试,同样的问题出现了。回到绘图板上为我解决这个问题。将尝试更多的东西,明天回到这个线程。现在来晚了
    • @joe - 偶然?请解释一下..顺便说一句,该属性是否是原子的对显示的代码没有任何影响。请注意我的警告,你的代码的其余部分不能有错误。
    • 我目前正忙于工作,但我将提供一个示例来说明保留周期和过早释放的问题(您的示例中可能会发生这种情况)。
    • @glogic - 出现了同样的问题?也许显示一些来自 MyClass 的代码?
    猜你喜欢
    • 2021-11-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    • 2013-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多