2012-02-02 3 views
5

나는 얼마 동안 프로젝트에서 작업 해 왔고 ARC로 점프하기로 결정했다. 매번 폭탄을 터뜨리는 코드를 발견했습니다. 이유를 알고 싶습니다. 나는 4 개 개의 다른 프로젝트에서이 피곤, 여기에 무슨 일이 일어나고 있는지 아주 확실하지 않다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; 
} 

, 그들은 모두 실패 :이 조각에 그것을 아래로 단순화하는 관리했다. 내 malloc 전화에 문제가 있습니까? 때로는 null을 반환하고 다른 경우에는 액세스 할 수없는 포인터를 반환합니다.

+0

왜 typedef입니까? 그렇지 않은 객체 포인터는'__strong'으로 간주됩니다. –

+0

실제 프로젝트에서 'MYID'는 struct (cocos2d의 ccCArray)의 일부이기 때문에. 또한 소유자가 'self'일 수있는 선택자의 일부가 아니기 때문에 코드는 소유권에 대한 한정자없이 컴파일되지 않습니다. –

+0

소유자가 '자기'가 될 수있는 선택자의 일부가 아니기 때문에 "당신이 의미하는 바가 확실하지 않습니다." " 메소드에 할당 된 객체의 "소유자"는 스택 자체이며'self'의 값이 아닙니다. 또한 ARC 아래의 C 구조체에'__strong' (또는'__weak') 객체 포인터를 넣을 수 없으므로'__unsafe_unretained'를 사용하고 명시 적으로 메모리를 관리해야합니다 (예 : 일부 ARC가 아닌 코드 또는'CFRetain() /'CFRelease()'). –

답변

13

크래시는 malloc 된 메모리를 객체의 C 배열에 캐스팅하기 때문에 발생합니다. 슬롯 중 하나에 할당하려고하면 ARC가 이전 값을 해제하여 쓰레기 메모리가됩니다. 0이 아닌 메모리를 얻으려면 malloc() 대신 calloc()을 사용해보십시오. 정상적으로 작동합니다. 그런 다음 realloc()을 필요로하는 경우 당신이 할 수 있습니다 귀하의 realloc() 전화도 할당있어 새로운 메모리를 제로-기입하지 않습니다

참고는 다음 객체에 할당하기 전에 수동으로 제로 채우기 임시 void* 포인터를 사용하는 것으로 정렬.

+3

dang. 세밀한. 이 인스턴스에서 ARC를 사용하려면 retain/release/C에 대해 많이 알아야합니다. – nielsbot

+0

고마워 케빈, 그게 다야. –

+0

@nielsbot : Obj-C를 고수하는 한 문제는 없을 것입니다. 이런 종류의 일은 기본적인 C를 결합하려고 할 때 (예를 들어'malloc()'과 같은) ARC와 결합 할 때만 생긴다. –

8

malloc 함수는 할당 된 메모리를 0으로 만들지 않습니다. 메모리는 임의의 쓰레기를 포함 할 수 있습니다. Clang Automatic Reference Counting 안내에서

, 4.2 : __strong 개체 용

새로운 pointee 먼저 유지된다; 둘째로, lvalue는 원시적 인 의미론으로로드됩니다. 셋째, 새로운 pointee는 원시 의미론을 사용하여 lvalue에 저장됩니다. 마지막으로 구 포인트 티이 출시됩니다.

여기서는 아마 malloc이 임의의 0이 아닌 값이 들어있는 메모리를 반환하고 있습니다. ARC는 임의의 값을 객체에 대한 포인터로 사용하고 해제하려고 시도하지만 올바른 객체 포인터가 아닙니다. 추락.