2011-09-08 2 views
2

간단히 말해서, 간단한 게임을 개발 중이고 나중에/유용 할만한 몇 가지 추가 사항은 물론 현재 게임 상태를 추적하는 Game 개체가 있습니다. 이들 중 하나는 단순히 객체에 속성으로 선언 된 게임,로드 UIViewController에 대한 참조 :왜 포인터가 변경 되었습니까?

@interface Game : NSObject { 
    //ivars 
} 

@property (nonatomic, retain) myViewController* viewController; 

게터 /이 속성에 대한 세터 @synthesize viewController을 사용하여 생성됩니다, 모두 잘 보인다.

이제 게임에 이길 때와 게임이 손실되었을 때이 속성에 액세스 할 수있는 경로는 두 개뿐입니다. "게임이 손실되었습니다"경로가 정상적으로 작동합니다. "game is won"경로가 viewController 포인터의 값이 가비지로 덮어 쓰여지는 이상한 오류가 발생합니다. 다음과 같이

은 무슨 일이 일어나고 있는지 파악하기 위해, 나는 getter 및 setter를 오버라이드 :

- (myViewController*) viewController { 
    NSLog(@"Getting"); 
    return viewController; 
} 

- (void) setViewController:(myViewController*)controller { 
    NSLog(@"Setting"); 
    viewController = controller; 
} 
을 ... 그리고 뷰 컨트롤러 인 내가 보유하고 있지 않다 내가 아는 (내부에 중단 점을 설정 내 setter하지만 그게 문제가 아니며보기 컨트롤러가 스택에 남아 있고 실제로 Game에 의해 유지 될 필요는 없습니다. 여기에 내가 GDB에있어 무엇 :
//first call to setter 
po controller 
<myViewController: 0x9208130> 

//call to getter on the "game is lost" path 
(gdb) po viewController 
<myViewController: 0x9208130> 

//call to setter, starting a new game from the same view controller 
(gdb) po controller 
<myViewController: 0x9208130> 

//call to getter on the "game is lost" path 
(gdb) po viewController 
0xbea2222c does not appear to point to a valid object. 
(gdb) print viewController 
$1 = (myViewController *) 0xbea2222c 

그래서 어떤 시점에서, 포인터의 값은 0x9208130에서 0xbea2222c로 변경되었습니다,하지만 난 곳을 알아낼 수 없습니다. 게임 시작시 setter 호출 외에도 viewController 속성 (또는 뒷받침하는 ivar)에 할당하는 코드는 없습니다. 그러나 분명히 무언가가 "game is won"경로에서 쓰레기 값을 덮어 쓰고 있습니다.

버퍼 오버런 문제 일 수 있습니까? 그렇다면 그것을 추적하기위한 좋은 접근법은 무엇입니까?

나는 놀이의 시작 game.viewController의 값으로 설정하고,이 포인터를 사용하여 (AN 다른 클래스에서 바르으로) 두 번째 포인터를 추가

편집 "게임 원은"경로 공장. 그래서 뭔가가 원래 포인터를 쓰레기로 내게 나타납니다. 그러나 아직도 어떤 생각이 들지 않습니다.

+0

가비지 수집기는 개체를 다른 주소로 이동 시키지만 참조에 영향을 미치지 않아 영향을받지 않습니다. –

+0

@Ryan - 자동 가비지 수집을 사용하지 않습니다. 가비지 수집기가 객체를 이동하고 포인터를 업데이트 한 경우에도 여전히 동일한 객체를 가리켜 야합니다. GDB에 따르면'0xbea2222c'에 존재하는 것은 더 이상 같은 대상이 아닙니다. 또한 가비지 컬렉터는 "게임이 이뤄졌습니다"라는 경로에서만 트리거됩니까? – aroth

+0

단순한 설명을 드려 죄송합니다. 그러나 Leaks 계측기 프로파일 링 작업을 올바르게 수행 했습니까? 그게 너 한테 뭐라고 했니? – darvids0n

답변

1

게시 한 정보로 문제를 진단하기에 충분한 데이터가없는 것처럼 보입니다.

이 문제를 더 디버깅하려면 포인터 ivar 메모리의 주소에 중단 점을 설정하는 것이 좋습니다. 그런 식으로 세터가 사용하지 않은 채로 변경되면 통보를 받게됩니다.

게임 개체를 만드는 동안 어느 시점에서 깨고 게임 개체의 컨트롤러 ivar에서 "변수보기"를 선택하면됩니다.

또는 asksol은 다른 질문 인 here에 대한 응답으로 Xcode 외부와 비슷한 방식으로 gdb를 사용하는 좋은 예입니다.

+0

고마워,이 문제를 해결하자. 사실 그것은 버퍼 오버런 문제였습니다. 기본적으로 나는 수준별로 인덱싱 된 상태 정보 배열을 가지고 있습니다 (각 수준에 대해 하나의 항목). "game is winning"경로에서 레벨은 마지막 실제 레벨을 넘어서서 증가하고이 상태 배열에 대한 액세스는 범위를 벗어났습니다. 문제를 해결하고 해결했습니다. – aroth

3

설정자가 잘못되었습니다. 읽어야합니다 :

- (void) setViewController:(yeticonfettiViewController*)controller { 
    NSLog(@"Setting"); 
    [viewController autorelease]; 
    viewController = [controller retain]; 
} 

그렇지 않으면 컨트롤러를 유지하지 못하고 가비지 수집 될 가능성이 있습니다.

+0

네, 그 증상은 완벽하게 맞습니다. –

+0

나는 이것이 문제가 아니라는 것을 내 질문에 언급하려고했다. (똑같은 일은 자동 생성 된 setter를 사용하여 일어난다.) 뷰 컨트롤러는 여전히 활성 뷰 컨트롤러의 스택에 있기 때문에 항상 유지됩니다. 'Game' 객체의 속성은 실제로 처음부터 '보유'로 선언 할 필요는 없습니다. 문제는 'UIViewController'가 너무 일찍 해제되거나 할당 해제되지 않는다는 것입니다. 그게 제가 제일 먼저 확인한 것입니다. – aroth

관련 문제