2011-03-28 41 views
0

我對釋放我首先分配/初始化然後複製的對象感到困惑。據我瞭解內存管理手冊我應該釋放對象2次,因爲通過分配它,然後複製它,我應該保留值2? 所以第一個版本會降低到一個和第二個0? 如果我釋放它兩次,我會將消息發送到dealloc對象。如果我一旦在應用程序中沒有出現問題,那麼我就可以做到這一點,但是我對理解對象C mem有一個瞭解。管理:)))發佈2次?

我能想到的唯一解釋是,當你從一個soecific上下文釋放一個對象時,它會立即釋放它,無論保留數的值是多少?

在片斷波紋管XMLELEMENT是混亂的一個....

// LSnippet of code for TouchXML 
for (CXMLElement *resultElement in resultNodes) { 

    NSMutableDictionary *xmlElement = [[NSMutableDictionary alloc] init]; 

    // Create a counter variable as type "int" 
    int counter; 

    // Loop through the children of the current node 
    for(counter = 0; counter < [resultElement childCount]; counter++) { 

     // Add each field to the blogItem Dictionary with the node name as key and node value as the value 
     [xmlElement setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]]; 
    } 

    // Add the blogItem to the global blogEntries Array so that the view can access it. 


    [tempReturnedElements addObject:[xmlElement copy]]; 
    [xmlElement release];  
    //[xmlElement release]; but NOT! 


} 

UPDATE:整個方法的代碼:

+(void) runXPath:(NSString *)xPathExpression{ 

CXMLDocument *rssParser = [[[CXMLDocument alloc] initWithXMLString:xmlStringContent options:0 error:nil] autorelease]; 

// Create a new Array object to be used with the looping of the results from the rssParser 
NSArray *resultNodes = NULL; 


// Set the resultNodes Array to contain an object for every instance of an node in our RSS feed 
resultNodes = [rssParser nodesForXPath:xPathExpression error:nil]; 

NSMutableArray *tempReturnedElements = [[NSMutableArray alloc]init]; 

// Loop through the resultNodes to access each items actual data 
for (CXMLElement *resultElement in resultNodes) { 

    // Create a temporary MutableDictionary to store the items fields in, which will eventually end up in blogEntries 
    NSMutableDictionary *xmlElement = [[NSMutableDictionary alloc] init]; 

    // Create a counter variable as type "int" 
    int counter; 

    // Loop through the children of the current node 
    for(counter = 0; counter < [resultElement childCount]; counter++) { 

     // Add each field to the blogItem Dictionary with the node name as key and node value as the value 
     [xmlElement setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]]; 
    } 

    // Add the blogItem to the global blogEntries Array so that the view can access it. 


    [tempReturnedElements addObject:[xmlElement copy]]; 
//***** Crushes if I use: 
//***** [tempReturnedElements addObject:[[xmlElement copy] autorelease]]; 
    [xmlElement release]; 



} 


[lotojuegosAppDelegate setMyReturnedXmlElements:[tempReturnedElements copy]]; 

[tempReturnedElements release]; 

}

由於提前, 盧卡

回答

2

規則很簡單:每個alloc/initcopyretain必須當你想放棄所有權調用只有一個releaseautorelease。您只撥打了一個alloc/init,因此您只能撥打release一次。

這條線:

[tempReturnedElements addObject:[xmlElement copy]]; 

應該寫成:

[tempReturnedElements addObject:[[xmlElement copy] autorelease]]; 

的原因是:copy爲您提供了一個新的對象。 xmlElement指向的對象的保留計數/所有權保持不變,但新對象現在屬於您。你現在負責發佈它。看到這個答案的第一段:你調用了副本,你需要調用釋放所產生的對象。

+0

好的,我不知道複製不會改變原始對象的保留計數。我的意思是我讀了 ,但我忘了這個。感謝這一個...。 如果我知道了它... 複製創建xmlElement的副本,並保留這兩個對象是1. 由於複製的對象沒有分配給任何其他對象(如在KennyTM的答案),我不能調用[xmlElement發佈] 兩次,因爲它不知道我釋放哪兩個xmlElement(分配或複製)? 這就是爲什麼你使用autorelease? – luigi7up 2011-03-29 13:52:29

+0

幾乎正確:'xmlElement'變量仍然指向原始對象,因此係統確實知道您正在與哪個對象交談,並且正確地說它的保留計數是1.因此,只有一個'release'需要。現在我們需要照顧副本:您可以捕獲指向副本的指針,像@KennyTM建議的那樣,稍後在該變量上調用'release'或直接在副本上調用'autorelease'(它的返回值是它被調用的對象)。使用'autorelease'你基本上說:*嘿autorelease池,你現在是所有者,稍後發佈它,kthxbye。* – DarkDust 2011-03-29 14:24:15

+0

非常感謝你的澄清:)很少有問題出現... 1.如果字典實現保持保留所有內容爲什麼我們發送複製的元素而不是原始的?在字典釋放其保留之前,原始對象不應被刪除?到目前爲止我看到的所有使用字典的代碼都使用這種技術addObject:[object copy]。 不應該addObject:object是否足夠? 2.對象在調用addObject方法後還是在當前上下文結束後立即插入字典中? Thnx – luigi7up 2011-03-29 17:02:20

4

[xmlElement copy]中,只有返回的對象(i .E。該副本)需要被釋放。接收者(xmlElement)的所有權(保留計數)不變。

所以,正確的做法應該是

NSDictionary* xmlElemCopy = [xmlElement copy]; 
    [tempReturnedElements addObject:xmlElemCopy]; 
    [xmlElemCopy release]; 
    [xmlElement release];