[英]Why does releasing my array crash my app?
如果我將第一個數組復制到第二個數組后發布我的應用程序崩潰。 如果我自動釋放第一個陣列一切正常。 為什么? 有沒有更好的方法將第一個數組復制到第二個數組?
如果我調用此方法,我得到一個ECX_BAD_ACCESS,我傳遞一個空數組
-(NSArray *)loadSystemDetails
{
AssortedCodeSnippets *acs = [[AssortedCodeSnippets alloc] init];
NSArray *details;
NSString *fp = [self tempPathAndFileName:[self systemDetailsFileName]];
if ([acs fileExistsAtPath:fp]) {
NSArray *array = [[NSArray alloc] initWithContentsOfFile:fp];
details = array;
[array release];
} else {
NSLog(@"No File to Load");
CreateSystem *cls = [[CreateSystem alloc] init];
details = [cls loadData];
[cls release];
[self saveDataFile:details toPath:fp];
}
NSLog(@"details: %@",details);
[acs release];
return details;
}
如果我自動釋放陣列它工作正常。
-(NSArray *)loadSystemDetails
{
AssortedCodeSnippets *acs = [[AssortedCodeSnippets alloc] init];
NSArray *details;
NSString *fp = [self tempPathAndFileName:[self systemDetailsFileName]];
if ([acs fileExistsAtPath:fp]) {
NSArray *array = [[[NSArray alloc] initWithContentsOfFile:fp]autorelease];
details = array;
} else {
NSLog(@"No File to Load");
CreateSystem *cls = [[CreateSystem alloc] init];
details = [cls loadData];
[cls release];
[self saveDataFile:details toPath:fp];
}
讓我們一步一步
密鑰:M =釋放/保留消息,C =釋放/保留消息的總和
// +----+---+
// | M | C |
// +----+---+
NSArray *array = [[NSArray alloc] initWithContentsOfFile:fp]; // | +1 | 1 |
details = array; // | 0 | 1 |
[array release]; // | -1 | 0 |
// +----+---+
此時您可以看到您將返回計數為0的details
,因此已經取消分配=崩潰。
復制是錯誤的術語,因為您實際上並不需要副本,因此您只希望指針details
指向有效對象,因此以下內容會更正確
- (NSArray *)systemDetails
{
NSString *filePath = [self tempPathAndFileName:[self systemDetailsFileName]];
NSArray *details = [[[NSArray alloc] initWithContentsOfFile:filePath] autorelease];
if (!details) {
NSLog(@"No File to Load");
CreateSystem *cls = [[CreateSystem alloc] init];
details = [cls loadData];
[cls release]; cls = nil;
[self saveDataFile:details toPath:filePath];
}
NSLog(@"details: %@",details);
return details;
}
在這里,我正在利用NSArray的方法
initWithContentsOfFile:
... [return]如果無法打開文件或文件內容無法解析為數組,則為nil
這減少了一些殘余並使該方法更容易閱讀。 我還將變量名稱擴展為有意義的名稱(個人偏好)。
我還重命名了方法,因為load
藝術是超級的,因為基本上你正在返回系統細節,它們被加載的事實並不是方法調用者真正關心的事實。
同樣重要的是要注意,其他答案建議您進行額外的保留/復制,然后記得稍后發布返回的結果。 這違反了cocoa約定,因為方法名稱不包含new / init / copy,因此方法的調用者不應該最終擁有結果。
發送details
信息時分配retain
消息,分配指向array
details
或cls
的-loadData
方法的結果。 請務必在-loadSystemDetails
方法之后的某處release
details
。
在您的代碼示例中,您實際上並未將array
復制到details
。 請記住,這兩個變量都是指向數組的指針 ,而不是數組本身。 因此,line details = array
只是將array
的位置復制到details
。 換句話說,在這一行之后,兩個變量都指向內存中完全相同的數組。 因此,當你調用release
,在內存中的對象被釋放,並且兩個 details
和array
正在指向一個不存在的對象。 如果要將數組實際復制到內存中,請使用
details = [array copy]
請記住,當你想要擺脫這個對象時,最終你必須在details
上調用release
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.