2012-03-21 3 views
3

명확하게해서는 안되는 릴리스 빌드에서 오브젝트 (ivar, NSMutableDictionary)가 삭제되는 iOS 게임 (ARC와 함께 컴파일 됨)에 케이스가 있습니다. . 디버그 빌드에서 모든 것이 좋습니다.오브젝트를 삭제하지 않는 경우 ARC를 디버그하는 방법

이 문제를 디버깅하는 가장 좋은 방법을 찾으려고합니다. 내가 어떤 종류의 수표를 물건에 대고 놓는다면, 그 물건은 꼭 돌아 다니기 만하면됩니다. 응용 프로그램이 충돌하여 개체가 사용 중이라는 것을 알았습니다. 따라서 개체가 액세스되고 있습니다.

좀비 오브젝트를 사용하여 오브젝트가 삭제되고 있음을 알았지 만, 어디에서 언제 일어나는지 알 수 없습니다.

컴파일러가이 객체가 더 이상 필요하지 않거나 실제로 삭제 될 때를 알 수있는 방법이 있습니까 (자동 복구 풀에있는 경우 아무 것도 말해주지 않을 수도 있음).

누구든지이 문제를 추적하는 데 유용한 조언이 있습니까? 나는 이것을 컴파일러 버그라고 부르기를 주저하지만 컴파일러가이 객체가 더 이상 참조되지 않는다고 생각할 수있는 것을 볼 수 없다. ivar를 보유하고있는 객체는 모든 코드가 실행되는 곳이므로 분명히 여전히 주위에 있습니다 (그리고 그렇지 않은 경우 훨씬 더 나쁜 일들이 일어날 것입니다).

지금은 개체를 삭제하지 못하게하는 디버깅 코드 한 줄을 남기고 있지만 해당 솔루션으로 응용 프로그램을 출시하는 것은 싫어합니다.

감사합니다.

+0

이 문제에 대한 추가 정보가 있습니까? 방금 ARC가 유지해야하는 객체를 삭제하는 것을 다루는 -O0 이외의 다른 최적화로 컴파일 할 때 충돌이 발생했습니다. – fbrereto

+0

xcode가 업데이트되면 버그가 나에게 돌아갔다. 그래서 컴파일러 문제라고 생각합니다. 그것은 9 개월 전이었고 그 이후로 문제가있었습니다. –

+0

감사합니다. CGPoint를 단지 Objective-C 클래스의 멤버가 아닌 속성으로 만들었던 것은 이상한 문제였습니다. 이상하지만 적어도 문제는 해결되었습니다. – fbrereto

답변

1

디버깅 코드를 넣을 곳은 개체의 dealloc 메서드입니다. 여기에 중단 점을 넣을 수 있습니다 (릴리스 모드에서도).

대부분의 원인은 일부 코드가 릴리스에서 다시 정렬되거나 제거된다는 것입니다.

"장소의 모든 곳에서 참조됩니다"라고 말하면 해당 속성에서 강하게 참조하는 개체가 있음을 의미합니까? 메모리 관리의 첫 번째 규칙은 당신이 신경 써야 할 것을 보존 (ivar 넣기)하고, 더 이상 신경 쓰지 않는 것을 해제하는 것입니다. 이 객체를 염려하는 객체가 있으면 강력한 속성을 가리켜 야합니다. 그들이 그렇게한다면 그것은 분명히 없어지지 않을 것입니다.


ARC에서 강력한 포인터를 매달므로 코드에 심각한 문제가 있음을 나타냅니다. 나는 브리징 캐스팅 (특히 __bridge)을 사용하여 어디에서든지 찾아 볼 것입니다. void 포인터에 객체를 잘못 전달하지 않았는지 확인하십시오.

C 배열 사용에주의하십시오. C 배열의 끝에서 벗어나면 다른 종류의 메모리가 손상되어 이러한 종류의 문제가 발생할 수 있습니다.

NSData과 같이 length 인수를 사용하는 모든 용도의 사용을 감시하십시오. 값을 너무 길게 전달하면 데이터의 끝에서 벗어나 다른 변수를 손상시킬 수 있습니다. 마찬가지로 malloc 메모리를 통한 원시 포인터가있는 모든 것.

+0

문제의 객체는 NSMutableDictionary이고 하나의 ivar에 보관되어 있지만 코드 전체에서 참조되므로 컴파일러가 더 이상 사용하지 않는다고 생각한다고 생각합니다. dealloc에 ​​중단 점을 넣을 수 있도록 서브 클래 싱을 시도 할 것입니다. 컴파일러가 더 이상 사용되지 않고 삭제한다고 생각하면 ARC가 컴파일러의 일부 마법이기 때문에 그 일에 대해 무엇을해야할지 모르겠습니다. 우리가 꽤 똑바로 보이는이 같은 것을 골치 르기 만하면 이상하게 느껴집니다. –

+0

글쎄, 그렇게 쉽게 끝난다. NSMutableDictionary를 후프 점핑을 많이하지 않고 서브 클래 싱 할 수는 없습니다. NSMutableDictionary의 dealloc을 깨뜨리는 더 쉬운 방법이 있습니까? –

+0

죄송합니다. 나는 그 물건이 사전이라는 것을 놓쳤다. 서브 클래 싱을하면 근본적으로 바뀔 것입니다 (더 이상 무료 교량 클래스가 아닐 것입니다). 그러나 코드가 사전을 "참조"한다는 사실은 그것에 대한 강력한 참조가 있는지 여부와 관련이 없습니다. 그것이 강한 ivar에 있다면, 그것은 살아 있어야합니다. 그렇지 않은 경우 언제든지 사라질 수 있습니다. 그것이 ivar에있는 동안 사라지면, 그 ivar에있는 것은 틀린 것일 수 있습니다. 그리고 그것이 실제로 생각할 때 그것이 ivar에없는 이유를 파헤쳐 야합니다. –

1

오늘 우리는 당신이 여기 들어간 것과 같은 소리로 문제가 발생했습니다. 우리는 plist 파일에서로드 된 NSDictionary의 사용자 정의 메서드를 사용하여 클래스를로드하고 있으며 이제는 double release와 같은 방식으로 해당 메서드가 끝날 때 응용 프로그램이 충돌합니다. 우리는 릴리즈 바이너리의 최적화를 막는 것이 우리가 해결할 수있는 전부라는 것을 알게되었습니다.

관련 코드를 현재 충돌을 일으키는 방법으로 변경하지 않았습니다 (약 2 개월 동안 정상적으로 실행되었습니다). 그리고 문제가 발생한 곳을 찾아내는 데 많은 시간이 걸렸습니다. 현재 해결할 수있는 유일한 방법은 출시 코드에 대해 '최적화 수준'을 '없음'으로 변경하는 것입니다. 이동에 ..

프로젝트 -> 대상 -> 바이너리 이름 -> 빌드 설정 -> 최적화 레벨 ->

을 해제로 설정 '없음 -O0'.

나는 옵티 마이저에서 발생하는 매우 이상한 버그가 있다고 추정 할 수 있지만, 이것이 당신을 도울 수 있기를 희망합니다!

+0

많은 조사 끝에 문제가 컴파일러 문제인지 확신합니다. 방금 xcode 4.3을 설치 했으므로 되돌아 가서 이것이 지속되는지 확인해야합니다. 그렇다면 애플 버그를 제출해야합니다. –

1

약한 IBOutlets가 있지만 나에게도 마찬가지입니다.

@property (nonatomic, weak) IBOutlet UIView *blahView; 

… 

[self.blahView removeFromSuperview]; 
[self.otherView addSubview:self.blahView]; 

첫 번째 라인 컴파일러는 객체에 대한 참조가 더 이상 없다고 생각하고 해제/해제합니다.

약한 참조 ivar를 유지하고 (범위에서) 임시 변수를 사용하면 컴파일러가이를 해제하지 못하게됩니다.

UIView *blahView = self.blahView; 
[blahView removeFromSuperview]; 
[self.otherView addSubview:blahView]; 

문제가 해결 되었습니까?

관련 문제