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

Ios 这种递归长轮询技术会导致堆栈溢出吗?,ios,objective-c,http,stack-overflow,long-polling,Ios,Objective C,Http,Stack Overflow,Long Polling,我在pastebin上看到了一个长轮询技术的示例,我想知道设计的递归性质是否会导致堆栈溢出?抱歉,如果这是一个noob问题,但我不熟悉长轮询,也不太熟悉objective-c //long polling in objective-C - (void) longPoll { //create an autorelease pool for the thread NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

我在pastebin上看到了一个长轮询技术的示例,我想知道设计的递归性质是否会导致堆栈溢出?抱歉,如果这是一个noob问题,但我不熟悉长轮询,也不太熟悉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.example.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
}
资料来源例如:

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

在C和Objective-C中,当调用函数时,堆栈帧被推到堆栈上。堆栈框架包含函数调用的数据,如函数参数和返回地址等。该信息占用空间,因此强制执行最大堆栈深度

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

- (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).
因此,您可以看到第二个示例通过异步调度递归而不是在自己的线程上同步调用递归来保持堆栈的平衡


根据

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

在C和Objective-C中,当调用函数时,堆栈帧被推到堆栈上。堆栈框架包含函数调用的数据,如函数参数和返回地址等。该信息占用空间,因此强制执行最大堆栈深度

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

- (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).
因此,您可以看到第二个示例通过异步调度递归而不是在自己的线程上同步调用递归来保持堆栈的平衡


根据

的说法,它可能不会破坏堆栈,但它会产生很多线程,这有时非常昂贵。@CodaFi,所以它会为每个递归产生一个新线程?这是一个实现细节。我相信如果有机会的话,它可能会实现,但希望他们变得更聪明,并在GCD之上实现它。选择器已经在后台执行,只需将其设置为延迟,它就会在同一线程上不断被调用。更好的是,将其重构为一个NSO操作,并生成一个私有队列。您可以更轻松地调试任何失败。它可能不会破坏堆栈,但它会生成大量线程,这有时非常昂贵。@CodaFi,因此它会为每个递归生成一个新线程?这是一个实现细节。我相信如果有机会的话,它可能会实现,但希望他们变得更聪明,并在GCD之上实现它。选择器已经在后台执行,只需将其设置为延迟,它就会在同一线程上不断被调用。更好的是,将其重构为一个NSO操作,并生成一个私有队列。您可以更轻松地调试任何故障。这有点令人困惑,但我想我明白您的意思。因此,当[self-performSelectorInBackground:@selectorlongPoll withObject:nil]时,所有这些NS对象都不会被放置在堆栈上;有人打电话吗?不完全是。这些对象都是在堆上分配的,不会影响堆栈大小。我更新了更多细节。谢谢你的详细解释,马特!这有点让人困惑,但我想我明白你的意思了。因此,当[self-performSelectorInBackground:@selectorlongPoll withObject:nil]时,所有这些NS对象都不会被放置在堆栈上;有人打电话吗?不完全是。这些对象都是在堆上分配的,不会影响堆栈大小。我更新了更多细节。谢谢你的详细解释,马特!