2009-10-04 47 views
0

如果我在發送-init之前發佈了NSOperation的實例,我得到segmentation faultMac OS X 10.6中的NSOperation中是否存在錯誤?

的原因,我認爲這是合法的代碼:

  • 蘋果做這its documentation
  • Gnustep在它的implementation of NSNumber中這樣做,所以相當肯定的是,這也是Apple的代碼。 (至少是。)
  • NSObject s -init沒有做任何事情,因此-release,它屬於NSObject應該在此之前工作。
// gcc -o test -L/System/Library/Frameworks -framework Foundation test.m 

#import <Foundation/Foundation.h> 

int main(int argc, char *argv[]) { 
    NSOperation *theOperation = [NSOperation alloc]; 
    [theOperation release]; 
} 
  • 你覺得,這是一個錯誤?
  • 你能告訴我一個具有相同行爲的另一個類的例子嗎?
  • 任何想法爲什麼會發生這種情況?
+0

@gs請閱讀我的評論回覆你的回覆:) – 2009-10-04 23:51:27

+0

我的觀點仍然支持:)。我確信NSOperation的'-init'會分配一些指針(指向結構或其他任何東西)。指針值不是由運行時設置爲NULL,所以調用'-release'釋放一個沒有啓動的指針,其值爲0(也就是你沒有訪問的地方:D) – 2009-10-05 10:40:57

回答

7

將除init以外的任何消息發送到尚未初始化的對象不是有效代碼AFAIK。調用超類初始化器,然後釋放,我敢打賭它不會崩潰(儘管有一個類的初始化器返回一個完全不相關的類會將我作爲doubleplusungood)。

+1

正確答案。記住更多細節。我實際編寫了一個測試項目,以確保這不是一個潛在的錯誤。事實並非如此。 – bbum 2009-10-04 18:47:23

+0

返回一個完全不相關的類就是爲了這個例子。我在我的工作代碼中沒有這樣做。 Gnustep的'NSNumber'類在初始化之前也會發送'-release'。我知道'-initWithCoder'永遠不會調用'-init'。 – 2009-10-04 18:49:56

+0

'initWithCoder:'方法通常會調用super。 – Chuck 2009-10-04 18:56:04

2

對於該代碼沒有任何遠程有效。

重寫你的-init爲:

- (id) init 
{ 
    if (self = [super init]) { 
     [self release]; 

     NSNumber *number = [[NSNumber alloc] initWithInteger:6]; 
     return number; 
    } 
    return self; 
} 

當然,代碼仍然是廢話,但它不會崩潰。

在發送消息之前,您必須始終調用super的初始化程序。而且您必須始終使用上面顯示的模式進行操作。

+1

我改變了代碼以避免更多關於代碼的討論。在初始化之前釋放有效:http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html#//apple%5Fref/doc/uid/TP30001163-CH22-SW13 – 2009-10-04 19:00:30

1

我以爲你需要在調用發佈之前初始化你的超類,但根據Apple的文檔中的this example,情況並非如此。

所以這可能是一個錯誤,但肯定不是一個重要的錯誤。

+1

我認爲你已經找到了一個文檔錯誤。 – Chuck 2009-10-04 18:51:36

1

我以前的分析並不是真的正確。

但是,我想指出,這個問題可能發生在不同的類。它實際上取決於你要繼承哪個類。例如,NSObject的子類化是沒有問題的,但是NSOperation,NSOperationQueue和NSThread的子類化是個問題。

它發生的原因就像你可能做的那樣,你的子類可能會在-init方法中分配這些東西。這也是您設置爲nil的變量,您尚未分配的變量(並且可能會在代碼中稍後執行)。

因此,在沒有以前的-init的情況下通過調用-release,可能會導致其中一個父類釋放它未分配的對象。而且他們無法檢查它們的對象是否爲nil,因爲它甚至沒有機會啓動它所需的每個對象/值。

這也可能是爲什麼在沒有init的情況下發布NSOperation的原因是10.5而不能在10.6上工作。 10.6實現已被重寫爲使用塊和Grand Central Dispatch,因此它們的initdealloc方法可能已經發生了很大的變化,從而在該代碼段上創建了不同的行爲。

+0

發送'-release'到一個無對象不應該做任何事情。另外,釋放'NULL'指針應該什麼也不做。 http://www.opengroup.org/onlinepubs/009695399/functions/free.html因此,我認爲這是一個錯誤。 – 2009-10-04 20:31:15

+0

@gs:我知道免費()並釋放NULL對象的工作。但是,當你甚至不希望它們將指針設置爲NULL/nil時,甚至不讓它們初始化它們的對象? (這是我在這個答案中的觀點)。在堆棧上分配指針不會將其設置爲NULL/nil。這就是爲什麼我認爲這不是一個錯誤。 – 2009-10-04 23:48:05

+1

Ivars在alloc中被自動設置爲零。 – Chuck 2009-10-05 04:30:11