2012-02-02 28 views
5

我一直在做一段時間的項目,現在我決定跳到ARC。 我遇到了一些每次都在轟炸的代碼,我想知道爲什麼。我設法簡化下來到這個片段:ARC&Malloc:EXEC_BAD_ACCESS

typedef __strong id MYID; 

int main(int argc, char *argv[]) 
{ 
    MYID *arr = (MYID *) malloc(sizeof(MYID) * 4); 

    arr[0] = @"A";  // always get an EXEC_BAD ACCESS HERE 
    arr[1] = @"Test"; 
    arr[2] = @"Array"; 
    arr[3] = @"For"; 

    // uh oh, we need more memory 
    MYID *tmpArray = (MYID *) realloc(arr, sizeof(MYID) * 8); 
    assert(tmpArray != NULL); 

    arr = tmpArray; 

    arr[4] = @"StackOverflow"; // in my actual project, the EXEC_BAD_ACCESS occurs here 
    arr[5] = @"Is"; 
    arr[6] = @"This"; 
    arr[7] = @"Working?"; 

    for (int i = 0; i < 8; i++) { 
     NSLog(@"%@", arr[i]); 
    } 

    return 0; 
} 

我不太清楚這裏發生了什麼,厭倦了這4個不同的項目,他們都失敗。我的malloc電話有問題嗎?有時它返回null,有時它返回一個我無法訪問的指針。

+0

爲什麼typedef?沒有其他限定的對象指針被假定爲'__strong'。 – 2012-02-02 20:36:33

+0

因爲在實際的項目中,'MYID'是一個struct(cocos2d的ccCArray)的一部分。此外,如果沒有所有權限定符,代碼將不會編譯,因爲它不是所有者可能是「自我」的選擇器的一部分。 – 2012-02-02 20:37:35

+0

我不確定你的意思是「因爲它不是選擇者的一部分,所有者可能是'自我'」。在方法中分配的對象的「所有者」是堆棧本身,而不是「self」的值。還要注意,你不能將'__strong'(或'__weak')對象指針放在ARC下的C結構中,你必須使用'__unsafe_unretained'並明確地管理內存(例如用一些非ARC代碼或'CFRetain()' /'CFRelease()')。 – 2012-02-02 20:40:37

回答

13

崩潰是因爲您將malloc'd內存轉換爲C對象數組。當你嘗試分配給其中一個插槽時,ARC將釋放先前的值,這將是垃圾內存。嘗試使用calloc()而不是malloc()來獲得歸零內存,它應該工作。

請注意,您realloc()通話也不會零填補所分配的新內存,所以如果你需要的realloc(),那麼你可能需要使用臨時void*指針,你再手動分配給你的對象之前填零陣列。

+3

dang。微妙。在這個例子中,你必須知道很多關於retain/release/C的知識。 – nielsbot 2012-02-02 20:39:40

+0

謝謝Kevin,就是這樣。 – 2012-02-02 20:41:21

+0

@nielsbot:只要你堅持Obj-C,你就不應該有問題。這種事情只會在試圖將基本C的東西(比如'malloc()')和ARC結合起來時纔會出現。 – 2012-02-02 20:41:23

8

malloc函數不會清零它分配的內存。內存可以包含隨機垃圾。

Clang Automatic Reference Counting指南,第4.2節:

對於__strong對象,新的指針對象首先被保留;第二,左值裝載了原始語義;第三,新的pointee用原始語義存儲到左值中;最後,舊指針被釋放

因此,這裏可能發生的是malloc正在返回包含隨機非零值的內存。 ARC嘗試使用該隨機值作爲指向對象的指針並釋放它,但它不是有效的對象指針。崩潰。