2010-04-22 133 views
0

我創建了一個調用Web服務的圖形應用程序。用戶可以放大圖形的移動範圍,程序偶爾會決定調用Web服務以獲取更多數據。這是通過以下過程實現的:Objective-C內存管理問題

該圖具有呈現循環,該循環不斷呈現圖形,以及將Web服務調用信息添加到堆棧的一些決策邏輯。

單獨的線程從堆棧中獲取最新的Web服務調用信息,並使用它來進行Web服務調用。堆棧中的其他對象被分類。

這樣做的想法是將Web服務調用的數量減少到僅適用的那些,並且一次只有一個。

權,與長故事的方式進行(對此我表示歉意),這裏是我的內存管理問題:

有圖有持續性(和適當鎖定)的NSDate *當前顯示的對象開始&圖表的結束時間。這些傳遞給我的Web服務請求對象的初始化程序。 Web服務調用對象然後保留日期。

Web服務調用完成後(或者如果它們已過期,則爲binned),它們釋放NSDate *。

該圖本身在「觸摸已結束」事件中釋放並重新分配新的NSDates *。

如果在調用removeAllObjects時堆棧上只有一個Web服務調用對象,則在Web服務調用對象的釋放方法嘗試釋放日期對象時發生EXC_BAD_ACCESS(即使它們看起來存在且處於作用域中在調試器中)。

但是,如果我從析構函數註釋掉釋放消息,則釋放堆棧上的一個對象時不會發生內存泄漏,但如果堆棧中有多個對象,則會發生內存泄漏。

我完全不知道怎麼回事。它沒有什麼區別我用於Web服務調用對象的存儲語義,因爲它們是在初始化程序中分配的,然後才被讀取(所以爲了正確性而設置爲只讀)。

如果我在初始化程序中保留或複製日期(儘管其他任何明顯超出範圍或在別處釋放並導致崩潰),似乎也沒有什麼區別。

對不起,這個解釋很長,我希望它已經足夠清晰,但我不是在賭博,或者我害怕。非常感謝任何能提供幫助的人,甚至提出我可能錯過的任何事情?

要明確希望事情了一下,這裏是一些僞(ISH)代碼...東西(不包括鎖和initialisers):

NSMutableArray* requests; 
NSDate* start, end; 

-(void)webServiceThread 
{ 
    if([requests count] > 1) 
    { 
     [self doRequestWithParams:[requests lastObject]]; 
     [requests removeAllObjects]; 
    } 
} 

-(void)render 
{ 
    if(conditions for another web service call are met) 
    { 
     WebServiceRequest* new = [[WebServiceRequest alloc] initWithDates:start :end]; 
     [requests addObject:new]; 
     [new release]; 
    } 

    [self doRendering]; 
} 

-(void)touchesEnded 
{ 
    [start release]; 
    [end release]; 
    start = [[NSDate dateSinceTimeInterval:chartLeft] retain]; //Ficticious NSDate Method names for example. 
    end = [[NSDate dateSinceTimeInterval:chartRight] retain]; 
} 

然後在Web服務調用對象:

NSDate* startDate; 
NSDate* endDate; 

-(void)initWithDates:start :end 
{ 
    startDate = [start retain]; 
    endDate = [end retain]; 
} 

-(void)dealloc 
{ 
    [super dealloc]; 

    //The following two lines cause EXC_BAD_ACCESS if this is the only object on the request stack. If they are commented, however, memory is leaked if this is not the only object on the request stack. 
    [startDate release]; 
    [endDate release]; 
} 
+0

這聽起來像是有一個釋放到很多。從你的解釋來看,這聽起來像是這個額外釋放發生的地方並不明顯。我想在某種程度上autorelease必須偷偷溜進去,你錯過了。如果您可以發佈相關代碼 - 所有作業,保留和發佈日期,這將有所幫助。 – 2010-04-22 13:49:57

+0

作爲一個小提示,儘管不需要,在'dealloc'中最後調用'[super dealloc]'最後通常更安全。 http://stackoverflow.com/questions/909856/why-do-i-have-to-call-super-dealloc-last-and-not-first – 2010-04-22 13:58:44

+0

感謝您的回覆,已添加僞代碼(實際代碼是大量的更長;也可能是問題的一部分)。自動釋放的想法沒有發生在我身上,但是在適用的情況下,所有東西都有一個存儲方法(目前保留)。 – Tobster 2010-04-22 13:58:58

回答

0

把[super dealloc]修好的問題;在destructor的結尾。感謝Toon Van Acker。

出於興趣;可以任意說,如果相同的原則適用於其他方法,如[超級初始化]?

+0

您必須最後調用[super dealloc]。一旦它被調用,你就不能保證你的任何ivars都有效了,因爲[super dealloc]最終調用了[NSObject dealloc],它釋放了內存並使其可以重用。 [super init]必須在你自己的任何初始化代碼之前完成,並且它的返回值賦給self。 – JeremyP 2010-04-22 14:59:47