Objective-C에서 예기치 않은 EXC_BAD_ACCESS
-
11-09-2019 - |
문제
다음과 같은 방법이 있습니다.
-(void)testAPIModule {
self.requests = [NSMutableArray array];
NSLog(@"making arrays");
/*(A)*/ id array1 = [NSArray arrayWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithFloat:2], nil];
/*(B)*/ id array2 = [NSArray arrayWithObjects:[NSNumber numberWithInt:4], [NSNumber numberWithInt:5]];
NSLog(@"made array=%@",array2);
for( ServerRequest *req in self.requests ) {
[Networker sendRequest:req withDelegate:self];
[req release];
}
}
코드가 예상대로 실행됩니다.
그러나 라인 (A)를 주석 처리하거나 라인 끝의 ",nil"을 제거하면 EXC_BAD_ACCESS
(B)행에 오류가 있습니다!디버거에 따르면 +[NSArray arrayWithObjects] 내장 생성자의 CFRetain에서 오류가 발생합니다.
또한 (A) 행을 주석 처리하고 for(...) 루프를 주석 처리하면 코드가 메서드를 통해 실행됩니다.
이것은 나에게 매우 예상치 못한 일입니다.(B)라인에서 내가 뭘 잘못하고 있는 걸까?그리고 (A)행에서 완전히 다른 배열을 생성하면 메서드가 실행되는 이유는 무엇입니까?그리고 왜 for(...) 루프를 주석 처리하면 그 앞에 있는 라인 (B)의 오류가 방지됩니까?
누군가 이것이 왜 설명할 수 있습니까?아니면 적어도 디버깅에 대한 조언을 주실 수 있나요?메소드가 한 번만 실행되고 "self"가 유효한지 이미 확인했습니다.
해결책
편의방식을 사용하는 경우 arrayWithObjects, 마지막 요소로 nil을 지정해야 합니다.
문서에 따르면 다음과 같습니다.
arrayWithObjects:
인수 목록의 개체를 포함하는 배열을 만들고 반환합니다.
+ (id)arrayWithObjects: (id)firstObj, ...매개변수
첫 번째Obj, ...
nil로 끝나는 객체의 쉼표로 구분된 목록입니다.
다른 팁
기타 경고 플래그에 -Wformat을 추가하면 컴파일러가 누락된 nil을 자동으로 찾아냅니다.
두 번째는 요소가 스택에서 모두 동일한 위치에 있기 때문에 첫 번째 이후에 작동합니다.따라서 첫 번째 항목에서 반환된 후에도 스택에는 여전히 다음 항목에 대한 포인터가 포함되어 있습니다. [NSNumber numberWithInt:1]
, 포인터 [NSNumber numberWithFloat:2]
및 nil(그리고 자동 릴리스 풀이 아직 배수되지 않았기 때문에 해당 포인터는 여전히 유효합니다!)nil 없이 두 번째 호출을 호출하면 스택의 포인터가 대체되지만 nil은 변경되지 않은 채로 남습니다.두 번째 시도에 세 개의 숫자가 있었다면 세 번째 숫자가 nil을 덮어쓰고 다음 숫자가 남게 되므로 같은 방식으로 충돌했을 가능성이 높습니다.