1

전무 나는 코드의 아주 간단한 라인 오브젝티브 C에있어 "을 사용! 때때로EXC_BAD_ACCESS OBJ =

if ((selectedEntity != nil) && [selectedEntity isKindOfClass:[MobileEntity class]]) 

나는이 라인에, 게임 충돌을 알 수없는 이유 EXC-BAD-ACCESS가있는 코드의 경우 일반적으로 무언가가 경기장에서 제거 될 때가 된 것 같습니다. 인 경우 추측하겠습니다. selectedEntity가 dealloc 된 다음이 결과가 표시됩니다. 존재하는 엔티티를 선택하는 것은 불가능합니다 (그러나 누가 내 코드에서 실제로 사실이 아님을 알고 있습니다 ...), 내가 특별히 거기에 있는지 확인하기 위해 인지 확인하기 전에 selectedEntity 여기에 문제가 있으면 안됩니다. Objective-C는 부울 short-citcuiting을 지원하기로되어 있지만 EDIT가 아닌 것처럼 보입니다. 단락이 문제와 관련이없는 것처럼 보입니다.

또한이 코드 블록 주위에 @ try/@ catch를 넣습니다. 왜냐하면 나는 매번 폭발하는 것을 알았지 만 무시당하는 것 같습니다 (EXC-BAD-ACCESS가 될 수 없다고 생각합니다.) 잡힌).

기본적으로 나는 누군가가 이걸 잡아서 버릴 수있는 방법을 알고 있는지 궁금해하고 있습니다. 왜냐하면 (게임 충돌을 일으키지 않는 한이 오류를 신경 쓰지 않기 때문에) 왜 그 이유를 설명 할 수 있습니까? 그것은 일어날 수 있습니다. Objective-C가 "nil"값으로 이상한 일을한다는 것을 알기 때문에 객체 포인터 나 nil이 아닌 이상한 공간을 가리키고 있다고 생각합니다.

편집 : 명확히하기 위해 아래 코드가 잘못되었다는 것을 알고 있습니다. 내 프로그램에서 추측 한 것입니다. 나는 이것이 문제를 야기하는지 물어 보았다. :-)

EDIT : 지워지기 전에 개체를 선택할 수있는 프린지 케이스가있는 것처럼 보입니다. 그래서, 코드의 진행은 다음과 같이 간다 나타납니다

그래서 오토 릴리즈 풀은 아직 발표되지 않았기 때문에, 객체가 nil이 아니라 그것의 유지 카운트가 그래서입니다 0입니다 같은데요
selectedEntity = obj; 
NSAutoreleasePool *pool = ...; 
[obj release]; 
if (selectedEntity != nil && etc...) {} 
[pool release]; 

어쨌든 액세스 할 수 없거나 그 라인을 따라 무엇인가?

또한 내 게임은 단일 스레드이므로 스레딩 문제가 아닙니다.

편집 : 두 가지 방법으로 문제를 수정했습니다. 첫째, 나는 그 프린지 경우 엔티티의 선택을 허용하지 않았다. 둘째, 단지 호출 [엔티티 removeObjectAtIndex : 내가] 대신 : 그냥 당신의 변수에 nil을 할당되어 있는지 확인

//Deselect it if it has been selected. 
if (entity == selectedEntity) 
{ 
    selectedEntity = nil; 
} 

[entities removeObjectAtIndex:i]; 

(코드가 삭제됩니다 어떤 요소를 제거하기 위해), 나는 그것을 변경 jib이 제안한대로 당신이 그것을 풀어주는 것과 동시에.

+0

-removeObjectAtIndex : 보유 횟수를 감소시키고 0에 도달하면 개체 할당을 취소합니다. 좀비가이를 감지 할 것입니다. 따라서 마지막 편집에서 nil을 지정하면 문제가 해결됩니다. – bbum

답변

6

개체 (selectedEntity)가 해제되고 dealloc 된 경우 == nil이 아닙니다. 이것은 메모리의 임의의 부분에 대한 포인터이다 (존재하는 경우 (selectedEntity 그것을 deferencing = 닐)는 프로그래밍 오류 (EXC_BAD_ACCESS)

컴먼 OBJ-C 패러다임 : -.

[selectedEntity 릴리스 ] selectedEntity = 전무,

+0

그게 내가 알아야 할 것이 었어. 고마워요! – Eli

+7

올바르지 않습니다. selectedEntity! = nil **은 EXC_BAD_ACCESS를 발생시키지 않습니다 **. EXC_BAD_ACCESS는 포인터를 참조 해제 할 때만 발생하며 오브젝트가 메세지 될 때 발생합니다. – bbum

+1

예, 오류가 발생하지 않고 항상 값을 확인할 수 있습니다. 메시지를 보낼 수 없습니다. – Eli

9

이것은 단락과는 아무런 관련이 없습니다. Objective-C는 메시지를 nil로 처리하므로, selectedEntity != nil에 대한 검사는 필요하지 않습니다 (messages-to-nil은 BOOL 반환 유형에 대해 NO를 반환하므로).

EXC_BAD_ACCESS는 잡을 수없는 예외는 아닙니다. 그것은 일반적으로 무효 포인터를 따라 가면서 발생하는 치명적인 오류입니다.

코드가 실행되기 전에 selectedEntity가 가리키는 객체가 모두 릴리스되었을 가능성이 높습니다. 따라서, 그것은 nil도 유효한 객체도 아니다.

NSZombies를 켜고 다시 시도하십시오.

앱이 스레드 된 경우 스레드간에 selectedEntity를 올바르게 동기화합니까 (일반적으로 보조 스레드에서 UI를 약화시키지 않는다는 것을 명심하십시오)?


소식이 수정임을 나타 내기 위해 편집 한 다음있는 NSMutableArray는 제거시에 객체를 -release 때문에

//Deselect it if it has been selected. 
if (entity == selectedEntity) 
{ 
    selectedEntity = nil; 
} 

[entities removeObjectAtIndex:i]; 

이 문제를 해결합니다. 보유 수가 0으로 떨어지면 객체는 할당 해제되고 selectedEntity는 할당 해제 된 객체를 가리 킵니다.

+0

당신은 나를 오른쪽 방향으로 지적했습니다. 내 편집이 당신에게 의미가 있는지 알 수 있습니까? – Eli

0

그냥이 http://developer.apple.com/mac/library/qa/qa2004/qa1367.html을 읽는 중 오류가 발생했다는 것을 나타내는 것은 개체를 과도하게 놓은 결과입니다. 이것은 선택된 selectedEntity가 nill이라는 것을 의미합니다. 여러 번 릴리즈 했으므로 더 이상 사용할 수 없습니다.

+0

이것은 항상 과도한 문제는 아니며,이 경우에는 아닙니다 (객체에 대한 릴리즈 나 유지를 절대로 호출하지 않습니다. 단순히 NSMutableArray에 추가되고 NSMutableArray에서 제거됩니다). – Eli

0

OBJC_EXCEPTION_THROW에 중단 점을 넣고 실제로 투구되는 부분을 확인합니다. 그 라인은 EXC_BAD_ACCESS를 절대로 던져서는 안됩니다.

예외가 발생할 수있는 IF 블록에서 뭔가를하고 있습니까?

0


selectedEntity = obj; 
NSAutoreleasePool *pool = ...; 
[obj release]; 
if (selectedEntity != nil && etc...) {} 
[pool release]; 

당신은 여기에 매달려 포인터 나 좀비를 가지고있는 selectedEntity 잘 당신이 selectedEntity를 참조하기 전에 자료를 얻을 수 OBJ에서 가리키는이 selectedEntity nil이 아닌하지만 그래서 어떤 잘못된 개체를 만듭니다.. 그것을 참조 해제하면 오류가 발생합니다.

obj를 해제하지 않고 자동으로 릴리스하려고했습니다.

+0

나는 분명해야했는데 - 나는 위의 코드가 문제라는 것을 알고있다. 그것은 내가 의심했던 것의 매우 단순화 된 버전이다. 올바른 코드인지 묻지 않았습니다. :-) – Eli