2013-07-08 6 views
1

저는 pastebin에서 긴 폴링 기법을 사용한 예를 보았고 디자인의 재귀 적 특성으로 인해 스택 오버플로가 발생하는지 궁금 했습니까? 미안, 이것이 멍청한 질문이라면 나는 롱 폴링에 익숙하지 않고 객관적으로 익숙하지 않다. c. 예를 들어이 재귀 적 긴 폴링 기법으로 인해 스택 오버플로가 발생합니까?

//long polling in objective-C 
- (void) longPoll { 
    //create an autorelease pool for the thread 
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 

    //compose the request 
    NSError* error = nil; 
    NSURLResponse* response = nil; 
    NSURL* requestUrl = [NSURL URLWithString:@"http://www.mysite.com/pollUrl"]; 
    NSURLRequest* request = [NSURLRequest requestWithURL:requestUrl]; 

    //send the request (will block until a response comes back) 
    NSData* responseData = [NSURLConnection sendSynchronousRequest:request 
          returningResponse:&response error:&error]; 

    //pass the response on to the handler 
    //(can also check for errors here, if you want) 
    [self performSelectorOnMainThread:@selector(dataReceived:) 
      withObject:responseData waitUntilDone:YES]; 

    //clear the pool 
    [pool drain]; 

    //send the next poll request 
    [self performSelectorInBackground:@selector(longPoll) withObject: nil]; 
} 

- (void) startPoll { 
    //not covered in this example: 
    // -stopping the poll 
    // -ensuring that only 1 poll is active at any given time 
    [self performSelectorInBackground:@selector(longPoll) withObject: nil]; 
} 

- (void) dataReceived: (NSData*) theData { 
    //process the response here 
} 

소스 : http://pastebin.com/3z5SM4R0

편집 : 이 잘못 형성 질문과 downvote의 합당 가난한 질문에서 저를 유지하기 위해 도움이 될 것입니다 무엇이 잘못되었는지에 대한 간단한 메모를하는 경우 미래. 그렇지 않으면, stackoverflow는 비우호하고 독점적 인 커뮤니티처럼 느껴지기 시작합니다.

+1

에 ¹According하지만 소년 안녕하세요 때로는 매우 매우 비싼 스레드를 많이 산란한다. – CodaFi

+0

@CodaFi 그래서 모든 재귀마다 새 스레드가 생성됩니까? – David

+2

구현 세부 사항입니다. 기회가 주어지면 도움이 될지도 모릅니다.하지만 GCD를 통해 더 똑똑해지고 구현되기를 바랍니다. 선택기가 백그라운드에서 이미 수행되고 있습니다. 지연시 설정하면 동일한 스레드에서 계속 호출됩니다. 더 나아가서 이것을 NSOperation으로 리팩토링하고 개인 대기열을 만드십시오. 오류를 쉽게 디버그 할 수 있습니다. – CodaFi

답변

5

아니요, 각 호출이 현재 스택에서 새 스택 프레임을 푸시하지 않기 때문에 코드에서 스택 오버플로가 발생하지 않습니다.

C (따라서 Objective-C)에서 함수를 호출하면 "스택 프레임"이 "스택에 푸시됩니다". 스택 프레임에는 함수 인수 및 반환 주소와 같은 함수 호출에 대한 데이터가 들어 있습니다. 이 정보에는 공간이 필요하므로 최대 스택 깊이가 적용됩니다.

함수가 호출 될 때마다 스택 프레임이 "푸시 (push)"됩니다. 함수가 반환 할 때마다 스택 프레임이 "팝"됩니다.

- (void)overflow 
{ 
    NSLog(@"Pushing..."); 
    [self overflow]; 
    NSLog(@"Popping..."); 
} 

인쇄 할 것이다 : 문제를 시각화하기 위해, 다음과 같은 방법을 참조

Pushing... 
Pushing... 
Pushing... 
Pushing... 
... (etc until overflow). 

을 당신이 볼 수 있듯이을, 함수는 반환하지 않습니다. 재발 할 때마다 다른 스택 프레임을 푸시합니다.

게시 한 예제의 차이점은 메서드가 직접 호출하지 않는다는 점입니다. 메서드를 즉시 호출하지 않는 performSelectorInBackground:withObject: 메서드를 사용합니다. 다른 스레드 ¹ (다른 호출 스택이 있음)에서 스케줄을 작성한 다음 즉시 리턴합니다. 따라서, 앞의 예 재 방문 :

- (void)overflow 
{ 
    NSLog(@"Pushing..."); 
    [self performSelectorInBackground:@selector(overflow) withObject:nil]; 
    NSLog(@"Popping..."); 
} 

지금 인쇄 것입니다 :

Pushing... 
Popping... 
Pushing... 
Popping... 
Pushing... 
Popping... 
... (etc forever). 

그래서 두 번째 예를 볼 수 있습니다 대신 스스로 동기를 호출하는 비동기 스케줄링 재귀에 의해 균형 스택을 유지 실.


그것은 스택을 분쇄하지 않을 수 documentation

+1

다소 혼란 스럽지만 나는 당신이 말하는 것을 보았습니다. 그래서 모든 NS 객체는 스택에 놓이지 않고'[self performSelectorInBackground : @selector (longPoll) withObject : nil]; – David

+1

정확하지 않습니다.이러한 객체는 모두 힙에 할당되며 스택 크기에 기여하지 않습니다. 나는 세부 사항으로 업데이트했다. –

+1

자세한 설명을 주셔서 감사합니다. Matt! – David

관련 문제