这种递归长轮询技术会导致堆栈溢出吗?

Dav*_*vid 1 stack-overflow http objective-c long-polling ios

我在pastebin上看到了一个长轮询技术的例子,我想知道设计的递归性质是否会导致堆栈溢出?对不起,如果这是一个菜鸟问题,但我不熟悉长轮询,我对objective-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
}
Run Code Online (Sandbox Code Playgroud)

来源例如:http: //pastebin.com/3z5SM4R0

编辑:如果这是一个形成不良的问题,值得一个关于什么是错误的快速记录将有助于阻止我在将来提出不好的问题.否则,stackoverflow开始感觉像一个不友好和独特的社区.

Mat*_*ing 5

不,该代码不会导致堆栈溢出,因为每次调用都不会在当前堆栈上推送新的堆栈帧.

在C(以及Objective-C)中,当您调用函数时,"堆栈帧"被"压入堆栈".堆栈帧包含函数调用的数据,如函数参数和返回地址(以及其他内容).该信息占用空间,因此强制执行最大堆栈深度.

每次调用函数时,都会"推送"堆栈帧.每次函数返回时,都会"弹出"堆栈帧.要可视化问题,请参阅以下方法:

- (void)overflow
{
     NSLog(@"Pushing...");
     [self overflow];
     NSLog(@"Popping...");
}
Run Code Online (Sandbox Code Playgroud)

那将打印:

Pushing...  
Pushing...  
Pushing...  
Pushing...  
... (etc until overflow).
Run Code Online (Sandbox Code Playgroud)

如您所见,该函数永远不会返回.每次递归时,它都会推送另一个堆栈帧.

您发布的示例中的差异是该方法不直接调用自身.它使用的performSelectorInBackground:withObject:方法不会立即调用该方法.它将它安排在另一个线程¹(使用另一个调用堆栈),然后立即返回.所以,重温前面的例子:

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

那将打印出来:

Pushing...  
Popping...
Pushing...
Popping...
Pushing...
Popping...
... (etc forever).
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到第二个示例通过异步调度递归来保持平衡堆栈,而不是在其自己的线程上同步调用它.


¹根据文件