2013-07-14 43 views
1

我花了最後一天的追捕動態存儲問題,並在路的盡頭的問題我不知道是怎麼回事其他比我一定誤解/錯過了一些關於繼承的NSString。這裏是有問題大大減少和多儀器樣品:與子類的NSString

IDStringBug.h包含:

#import <Foundation/NSArray.h> 
#import <Foundation/NSString.h> 
/*==================================*/ 
@interface IDStringBug:NSString { 
    NSString  *_backingStore; 
    NSArray *path; 
} 
- (NSArray*) path; 
- (void)  dealloc; 
- (NSUInteger) length; 
-(id)   initWithString: (NSString*) string; 
-(unichar)  characterAtIndex:(NSUInteger) index; 
@end 

IDStringBug.m包含:

#include <stdio.h> 
#import "IDStringBug.h" 

@implementation IDStringBug 
- (NSArray*) path { 
    printf ("Return ptr to IDString: %s\n", [_backingStore cString]); 
    return path;} 

- (void) dealloc { 
    printf ("Release IDString: %s\n", [_backingStore cString]); 
    printf ("Path count is %d\n", (int) [path retainCount]); 
    [_backingStore release]; 
    printf ("Apres _backinstore\n"); 
    printf ("Path count is %d\n", (int) [path retainCount]); 
    [path release]; 
    printf ("After path release, done but for super\n"); 
    [super dealloc]; 
} 

-(id)initWithString:(NSString*)string { 
    if ((self = [self init])) { 
    _backingStore = [[NSString stringWithString:string] copy]; 
    } 
    path = [_backingStore componentsSeparatedByString: @"."]; 

    printf ("Path count is %d\n", (int) [path retainCount]); 
    return self; 
} 

-(NSUInteger) length { 
    return [_backingStore length]; 
} 
-(unichar)characterAtIndex:(NSUInteger)index { 
    return [_backingStore characterAtIndex:index]; 
} 
@end 

bug.m包含:

#include <stdio.h> 
#include <Foundation/NSAutoreleasePool.h> 
#import "IDStringBug.h" 

int main(int argc, char* argv[]) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    IDStringBug *myids  = [IDStringBug stringWithString: @"a.b.c"]; 

    printf ("Path count is %d\n", (int) [[myids path] retainCount]); 
    printf ("pool=%d\n",   (int) [pool autoreleaseCount]); 

    [pool release]; 
} 

的輸出是:

$ ./bug 
Path count is 1 
Return ptr to IDString: a.b.c 
Path count is 1 
pool=7 
Release IDString: a.b.c 
Segmentation fault (core dumped) 
+4

爲什麼你想要它的子類呢? – vikingosegundo

+3

http://whentouseretaincount.com – vikingosegundo

+0

您是否在使用ARC?如果沒有,那麼'_path'被分配給一個自動釋放對象('componentsSeparatedByString:'的返回值),並被過早釋放。 (另外,我在「after」之後發現了一個「après」,你是法語嗎?:)) – 2013-07-14 17:12:56

回答

2

componentsSeparatedByString:的調用返回已經被自動發佈的NSArray。這意味着它的保留計數爲1,但自動釋放池一耗盡,該計數就會減少。將它與IDStringBug dealloc中的release調用結合起來,就可以看到陣列被釋放了一次。

實際上由IDStringBug的dealloc被調用的時候,路徑陣列已經被釋放。所以,當你試圖確定保留計數(與調用[path retainCount]您嘗試訪問不再存在的對象。

+0

好的,這樣數組將不得不增加其保留計數。請注意,retainCount調用是指出我在子類中的懷疑,並且我懷疑這個路徑被重新分配了兩次,我只是看不出爲什麼。另外,我閱讀了「從不使用保留計數」這篇文章,但是如果沒有保留計數,我的分配失敗問題就更多了。作爲當前FoundationKit世界的「外人」(我在NeXT時代曾是一名內線人士,但大部分已經離開或僅使用Objc基地),我想謹慎地詢問聽起來非常像宗教領域的聲音; ) –

+0

我想補充一點,我一直使用科昌書作爲參考,但它談論分配/ dealloc的多少和保留計數,我得到的印象,甚至他也不太瞭解它是如何工作... ;-) –

+0

對於任何你還沒有創建的對象,如果你想獲得它的所有權,你需要調用'retain';當你完成它的時候'釋放'它。這在[Apple內存管理文檔](https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html)中有更詳細的解釋。在這種情況下,你想獲得從'componentsSeparatedByString:'返回的數組的所有權,所以你應該保留它。你已經在dealloc中釋放它,所以這部分是正確的。 –

6

這個答案並不直接解決您的問題,但它會間接地解決它,並導致。一個更容易維護的設計模式

別子類的NSString

取而代之的是,使用組成

@interface PathString:NSObject 
@property(copy) NSString *stringValue; 
@property(strong) NSArray *pathValue; 
... etc ... 
@end 

的實際碰撞是這樣的:。

path = [_backingStore componentsSeparatedByString: @"."]; 

該方法返回一個自動釋放對象,並在池被排空時釋放一個懸空引用,從而釋放該對象。

正如其他人所說,retainCountutterly useless

注意,這是奇怪的:

_backingStore = [[NSString stringWithString:string] copy]; 

這應該僅僅是:

_backingStore = [string copy]; 

你的代碼是技術上複製串的兩倍。我說的技術上,因爲 - 由於實施細節 - _backingStore最終將指向string(假設stringNSString,而不是一個NSMutableString

我是非常一位內部人士早在接下來的日子裏,。但一直以來主要是 以外或僅使用Objc基地。

啊哈!所以是我,其於1989年

開始ObjC編程那會解釋你在哪裏有點來了!

相反的retainCount,像這樣的問題是很容易使用殭屍進行調試。您可以在Xcode的方案的選項窗格中打開它。

的「whentouseretaincount.com」網站鏈接到一個article I wrote約保留計數。一般來說,您可能會覺得它有趣,它也闡明瞭內存管理的一些細節。

蘋果文件到Linux GNUstep的世界

這也是在你的問題要注意的關鍵。 GNUStep大部分就像Apple的東西,但更接近OpenStep世界。我不記得GNUStep是否有殭屍檢測,但我懷疑它會。 Linux也有其他內存調試工具,功能非常強大。

retainCount仍然會充斥着脆弱性,但有一個單線程的,命令行工具打交道時,它是較爲穩定的。不過,你仍然需要注意自動發佈的東西。

+0

你知道Randy Nelson,然後...... –

+0

我做到了!作爲NeXT校園顧問,我從他那裏接受開發人員培訓,然後繼續擔任偶爾的教師助理。 – bbum

+0

我在CMU在Roger Dannenberg的音樂實驗室工作,他做了很多音樂套件;我約89歲時參加了開發者課程(Randy在實驗室工作)爲一家Pgh創業公司工作;然後去了北愛爾蘭,並擔任QUB的校園顧問,並被邀請爲NeXT UK教授OO編程。所以我知道很多NeXT的人。仍然認爲這是有史以來最好的Unix計算機開發人員技術。 –